MVVM: Communication - wpf

I am working on a large MVVM application. I am using the MVVM light toolkit for this. The application is like a web browser with back and forward buttons. The main view is an user control. I laid the back and forward buttons in the main view user control. The main view in turn has user controls. The user controls change when the back and forward buttons are clicked. The main ViewModel keeps track of the current user control and loads the next one depending on the button click.
All these user controls are loaded depending on the selection(ID) made on the first step. Lets say, the main view is a search screen and we select a customer. The next screens would be Address, Billing, Requests, etc. These screens does not share any data. But the data is for the same customer.
So, is it a good practice, to store the customer ID in the main view? If I do this, I should have a UserControl_Loaded event bound to a command, where I would then request for Address and Billing Info.
Or I can move the buttons(back and forward buttons) to each user control instead of the main view, Pass the customer ID with the message which would load the next view.
Which is better?

A way I've done this sort of thing in the past is to implement a class that encapsulates the data context for the operation. All of the pages will be populated with (and update) properties of this class. The main view model creates an instance of this class and a collection of the page view models, providing each with the data context. It also handles navigation from page to page, implementing CurrentPage, NavigateForwardCommand, and NavigateBackwardCommand properties.
If the user backs up to page 1 and changes the customer ID, the data context is repopulated with the information appropriate to the new customer. Since all of the pages are looking at the same data context object, all of the subsequent pages will display the right information.
You'll need to implement property-change notification in the data context object, and handle PropertyChanged in the pages. When the CustomerID property changes in the data context object, the page view models will need to refresh properties that appear in their respective views.

Related

Looking for a way around Winforms 10,000 handle limit

I have been tasked with creating a like for like user interface for a product replacement.
One of the components of the old system was a container that displayed properties in a hierarchy (think treeview like) where each property had a label and value (value could be a textbox, drop down, checkbox, file browse etc)
This is the component that I need to replace and one of the conditions being imposed on me is to front load it with about 5000 items, some of which will be made visible depending on usage context.
My first attempt has been to use a FlowLayoutPanel as the main container populated by TableLayoutPanels indented on left margin that each hold label and edit control.
I hit the problem of the 10,000 control handles limit.
Any suggestions on an alterantive approach to get round this limitation that will allow for the front loading of the 5000 items?
Thanks in advance.
Consider the following guidelines:
1. Do not load all the records at once. Load the data page by page as per request, and render each page of data.
2. Do not show all the records at once. You have a limited window size, even if you load all the data, just show the part that should be visible in the view port. Show the rest of the data when the user scrolls. This way you can dispose the previous elements.
3. Do not use a lot of handles. You can use a control which uses just 1 control handle, like a TreeView or DataGridView or even a custom control for yourself. The key is keeping data in view mode and just show the edit controls when the user focus on a specific item to edit.
Example: DataGridView and ListView controls support virtual mode for loading data. You can also simulate nested data by padding the first cell/item. Also the Treeview control supports events like BeforeExpand which allows you to load child data when the user requests.
For all above examples you can just show the edit controls when the user wants to edit the cell.

Load view on double-click of row - have bindings working, and event being fired on click, but how do I actually get the view to pop up?

I have a view in Silverlight which contains a telerik:RadGridView with a number of columns.
I have it wired up so that when the user double-clicks on one of these columns, an event is fired. However, I don't know what to put in the event handler.
private void RowClicked()
{
//What goes here?
}
All I wish to do is load a popup view over my current view, with a close button so that the user can return to the previous view. A simple idea that is surely done a billion times everywhere, but I cannot figure it out or find examples of this anywhere.
Can anyone help?
Thanks very much.
You can set a previous view as input parameter to "RowClicked()" method. You will have a reference on previous view in current method. You can use it via Commands (bind a command and a command parameter to some action/event).
I have an one more idea (if you have a lot of views): you can create a navigation service. It is an interface, which contains events and methods. You should use events for navigation and methods - for sending needed data. Everyone of view should implement this interface. Needed event will be raised under view via some action (for example: button click). As for events: you can create a custom event handler, there you will set a sender instance and needed parameters. You should create a Navigation manager, there you should create a property for selected view and subscribe on everyone event. If user want navigate to another view, he will do some action and system will raise an event. You can create a custom container for created views. This container you can use for getting created instance of needed view. As you know, creating a new instance is heavy for system: need a some time and system resources. Will be easy to get a created instance of view instead a create a new. For setting default data or refreshing a binding you can user a custom method, contractor for which will be added to navigation interface.
It is a simple idea, which I used in one project. As for others samples: You can find another navigation frameworks and custom classes in internet. But, process of creating an own system will give you a level up in your work experience.

ViewModel -> Model interaction

Suppose I have a WPF/MVVM application for managing some hypothetical customers :).
Domain model contains an entity named Customer (represented as a POCO in code).
The main screen contains a grid, bound to a view model (CustomersViewModel) that loads its data from Repository< Customer>.
The main screen also allows to create new customers (and save it to the DB).
Suppose I need to implement 'add customer' use-case. The most obvious approach is as follows:
Present the user with a dialog window to be filled out with new customer data.
Handle 'Save' button click in the ViewModel.
Create customer (var new_customer = new Customer(..)) domain object using the data from the dialog (step 1).
Call Repository< Customer>.Save(new_customer) to save the new customer to the DB.
Reload CustomersViewModel with fresh data from the DB so that newly added customer is visible in the grid.
Personally I don't like this 'quick-and-dirty' way (because of need to reload the full list of customers from DB every time a new customer is added).
Can anyone suggest a better approach (that wouldn't require refreshing the customer list from the DB)??? I feel there gotta be some best practice for handling scenarios like that:) ).
Thanks in advance!
If the saving of the Customer is successful, why can't you just add that single Customer instance to your collection of customers? No need to re-load all customers unless the user explicitly refreshes the view (usually via a refresh button).
If you are loading the list in your view through a binding (to a list of customers) you can just add the new customer to that list and everything is alredy ;-)
I have a similar application where in the object is created in UI. I solve it by adding the object in VM and then syncing it with Model on click of Save button.
I am assuming you have a list of CustomerViewModel in CustomersViewModel to which the grid view is bound to. You can add a new CustomerViewModel object to the list in CustomersViewModel. While saving the ViewModel data back into the model, the model gets in sync with VM. No need to refresh VM back from Model unless somebody else apart from your app is changing the Model data.
You could create an ObservableCollection<Customer> and fill it with the customers from the database which you want to show in the View. When you add a new customer then add it to this collection as well as save it into the database. The CustomersView binds on the ObservableCollection and is updated automatically without the need to refresh the data from the database.
The BookLibrary sample application of the WPF Application Framework (WAF) shows how this can be done.

Managing silverlight RIA services context lifetime

I'm working on a line-of-business silverlight application and I need a piece of advice concerning managing RIA services context lifetime.
Application - afer a few simplifications - is build of one big tab control. At the beginning there are 2 tabs: customer list and invoice list. These are plain datagrids with filtering/sorting and that sort of stuff.
User can add/edit customer or invoice selecting a row and double-clicking. Then the new tab is created with details of customer or invoice. User can open many tabs with different customers/invoices. After editing, user can save and close tab or just abandon edit and close.
The question is how to deal with data contexts.
Should I create one for customerlist and one for invoicelist and when user opens a new tab, I simply bind customer/invoive dataobject to control? This has an advantage that I dont need to refresh grids after saving changes. EDIT: This has some drawbacks. User can refresh grid - and what will happen to open detail tabs? User can also filter grid so some records being edited can be removed from datactx?
The other way is to create datacontext per tabitem. This is more safe but I need to handle refreshing grid(s).
I have no idea which method is better or maybe there is another alternative?
Use one ObservableCollection list in each case and it will automatically update the datagrids when items are changed.

WPF access controls in a DataTemplate of a ListBox

I'm building a WPF order manager app and i've run into a situation i'm not sure how to deal with.
I want to re-bind the list of purchase orders requests for each order but i only want to do it if the the purchase order requests panel is visible in the app (they double click the order to show the list of purchase order requests). The problem i have is that the purchase order requests are a listbox inside each list item of the Order listbox and i can't find a way to traverse the controls in the list items (I can only iterate over the actual objects e.g. OrderInfo).
What i would like to do is
OrderListBox.FindName("PurchaseOrderListBox")
An example of the crm with 2 orders showing purchase order requests and 1 order not showing any
alt text http://www.readyflowers.co.uk/images/crm-datatemplate.png
The result i want to achieve
alt text http://www.readyflowers.co.uk/images/crm-datatemplate-saved.png
I'm not sure I understand your problem....
But it feels like you're trying to hack through the UI hierarchy to find something (ala WinForms) - this is like swimming against the tide in WPF. It'll make you tired real fast..
Look around for articles on the ViewModel pattern. One of them that I read is one by Dan Crevier. The basic idea is to have a Model object for the UI - the UI (data)binds to properties exposed by the ViewModel. Now all your UI related logic could go into the ViewModel, which is notified via propertyChanged notifications of any change in session state. So if a field changes, the ViewModel gets notified. The ViewModel updates relevant properties and the UI refreshes accordingly.
In this case ViewModel.OrderInfo.Find_PO_with_X(searchCriteria) will help you get to the right object. If found, you say ViewModel.ShowGreenLight = true and the UI control bound to this property will turn green.
HTH

Resources