Synching a modifiable list over multiple views in MVVM - wpf

I'm trying to learn MVVM for VB.NET and WPF. Now I've struck a situation where I can't find a way to handle it. The actual data in my program is very specific, so I'll use a similar construct here.
At first, there are departments. They do have a department manager. They are usual Models and do have a usual ViewModel.
Then, there are employees. They do have a name and an id. Employees are Models too and they do have a ViewModel.
It is planned to have a view to edit the list of employees.
There is a view to edit departments.
The department view has a dropdown to select the department manager from the employees.
Now my question: where and how do I manage the employees, so I can achieve that the drop down list of all departments are updated if new employees are added?
So far, I've used a singleton as EmployeeService that ensures 2 things:
5 employees are in the default list and cannot be modified.
Added entries are no duplicates regarding id.
The EmployeeService uses an ObservableCollection(Of Employee) to organize the models. Furthermore it offers a Public Property Employees As ReadOnlyObservableCollection(Of Employee).
The DepartmentViewModel has a Public Property EmployeeOptions As String() to populate the dropdowns. It adds an CollectionChanged event handler to the service's ReadOnlyObservableCollection (treating it as INotifyCollectionChanged) that refills EmployeeOptions and fires OnPropertyChanged("EmployeeOptions") afterwards.
However I feel this is not quite a good way to do this, is it?
I wonder if I should make a EmployeeServiceViewModel that wraps the EmployeeService and provides something like one ObservableCollection(Of EmployeeViewModel) for all DepartmentViewModel instances? On the one hand that means to have a singleton EmployeeServiceViewModel, and I always read "you shouldn't use view model singletons". On the other hand, the view to edit the employee list requires that EmployeeServiceViewModel anyways, right?
Has anybody a structure diagram or something where an editable list of models populates multiple view's dropdowns?

Related

How to assign context and refresh it in Entity Framework?

I created a new entity object and bound it to controls in another window (edit window). After modifying and saving I assigned a new entity object into the one in the main window. The old entity object is bound into a datagrid, now I want the datagrid to display the data that I had modified and saved.
ObjectContext.Refresh Method (RefreshMode, Object) seems to be what I want but I don't know how to use it correctly.
In short :
I have a main window with datagrid displaying the whole data of the table. Users can pick one row and edit it in a edit window. After saving, the datagrid should display what has been modified.
Your best bet here is to use an ObservableCollection as your data source for the datagrid instead of the query.
And look at implementing INotifyPropertyChanged interface in your Customer class.
The ObservableCollection is initially populated by the database query. User changes are made to elements within the ObservableCollection and once complete you then just need to trigger transferring the changes to wherever you originally obtained your list of Customer objects
By doing this changes made both to the collection of Customers and to individual Customer objects (if present within the datagrid) will be automatically updated for you.
edit
I must admit that I'm a bit rushed to offer up any code at the moment, but here's a pretty good article that explains how to use ObservableCollections and classes that implement INotifyPropertyChanged. It also has code examples, which although in VB.NET should give you enough of an idea to get started.
In effect you separate your code into distinct layers UI (View), business logic (View Model) and data layer (Model where your entity framework resides).
You bnd your datagrid to the ObservableCollection type property in your Customers class and your edit csutomer window is bound to as instance of your Customer class.

How to create the ViewModel(s) for many Views sharing the same Model?

This is based on the example from the book:
Pro WPF and Silverlight MVVM by Gary McLean Hall
where the author only insists on how to create the Model for a DB structure (and how to implement the DAL for it).
I am looking for the correct way to create the ViewModel(s).
Here is the database model and the MVVM Model- I suspect it is not quite complete, but the Product is missing the ProductCode:
My Views will be: Pages displaying / editing views for Products, Customers and Orders
I am familiar with the Models / ViewModels implementing / using the INotifyPropertyChange and ObservableCollection, no need to insist on that.
My questions:
How to create the ViewModels in such a way that they would all share the same model
How do I manage the ViewModels? Do I have one Main ViewModel which aggregates all the specific ones? This relates to ViewModel state saving and restoring.
I am particularly interested in how to deal with this: the Model for Order has a List of Products. I will also have to maintain a list of Products for my ProductsViewModel which supports the displaying / editing Views for the Products. How can all be synchronized? Should the OrderModel only have a List of ProductCodes instead? What are the implications in that case?
In general, the thing I am after here is: how to create and manage the ViewModels for Models which implement DB tables with many to many relationships (like Product-Orders). Do we use only the foreign keys as part of the Model objects or do we use a reference to a whole other Model object represented by that foreign key?
To me it sounds like you are thinking about it the wrong way round. When you ask "How to create and manage the ViewModels for the Models which implement DB tables with many to many relationships" it sounds like you are thinking about ViewModels in terms of Models. Which isn't right. A ViewModel is a model of a View - not the Model. You shouldn't be thinking about creating ViewModels for your models, you should be thinking about creating VewModels of your Views.
In fact the model doesn't even come into it until the end. Start with your UI - your View. You then create a logical representation of that View in code so that you can bind to it, your ViewModel. Then finally you implement your ViewModel by accessing your Model to do what ever needs to be done. When you come to design the next View, even though it might contain some of the same data as the first, you would still create a new model for it - another ViewModel. Now the new ViewModel could include some of the same properties at the first ViewModel, which is fine. Remember is is a model of the View not the Model.
Consider an email app, with 2 views, summary and detail. Because there are 2 different Views you have 2 different ViewModels even though the are both pulling data from the same underlying model.
Model SummaryViewModel DetailsViewModel
----- --------------- ----------------
RecipientAddress RecipientAddress
SenderAddress SenderAddress SenderAddress
Subject Subject Subject
Content Content
Now the Summary View is only a summary and doesn't display the RecipientAddress or the Content so consequently those properties don't exist on the SummaryViewModel. The Details View displays more information, so has more properties. This same idea answers your question about foreign keys. Foreign keys are never visible on your View therefore have no business being members of your ViewModel. Your ViewModel cares only about what is required for the View.
In answer to your question "how do you manage the view models": you don't. You don't have to. ViewModel instances usually (not not always) have a one to one relationship with the Views, therefore you don't need to manage them. They only live as long as the view lives. You just create a new instance of the ViewModel when the View is loaded (typically in OnNavigatedTo event handler, see below) and store it in the View's DataContext. If two instances of the View are loaded, then there are two ViewModels. When the View is GC'ed, the ViewModel is too (if it isn't you have a memory leak).
Finally, as for how you should synchronize changes, that can be tricky in a desktop Silverlight app where many views might display concurrently. Fortunately on the Windows Phone we usually only have one view open at a time (although not always). So we can simply tell our ViewModel to refresh each time the page is navigated to:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (DataContext == null)
DataContent = new MyViewModel(); //Create new instance of the ViewModel
else
(MyViewModel)DataContext.Refresh(); //Refresh the existing ViewModel
}
This works well in most cases for more advanced scenarios you could look at the messaging infrasructure provided by a toolkit like Prism or MvvmLight.
Hope this has helped.

How do you handle the deletion of your model working with ViewModels and keeping them in sync?

These could be my entity relations:
1 Pupil has 1 Chair
1 Pupil has N Documents
1 Pupil has N Marks
1 Pupil has N IncidentReports
etc...
So with that sample I get 4 IEnumerable from my database put each into an
ObservableCollection.
Now I have 4 different Views each bound to one of those 4 collections.
Lets assume I delete a single PupilViewModel in the AdministrationController which is the only View where I can delete a PupilViewModel.
Now I have to inform 3 other Controller and their ObservableCollections about the one deleted PupilViewModel to keep the whole application synchronized... thats stupid somehow.
Do you have any good advice on that scenario?
AND it gets even worse. If I delete a schoolclass I have to sync the pupils everywhere AND the documents or incidentreports or marks...
What I would suggest is using the EventAggregator from such frameworks as Prism, Caliburn. The fundermental thing about this is that you register interest in a known subject or object within each ViewModel and when a delete of a pupil comes along all ViewModels interested in knowing about the change can update (or synchronize) the ObservableCollections since the pupil (or id) is passed to all listeners.
Another alternative which might be more work would be to have one model object that all those ViewModels share an instance of. That model is responsible for updating the lists it has and provided it implements INotifyPropertyChanged and has the collections bound to the view then the Views will update.

MVVM WPF ViewModels for Adding New Entity

My concept for MVVM in WPF is that we have a ViewModel for every Model in your application. This means that if we have Customer class (entity) then we will have CustomerViewModel. The CustomerViewModel will have all the properties which are necessary to represent a customer. The CustomerView usercontrol will be responsible for creating the UI for the Customer model.
Now, let's say that we are adding a new customer. So, we have a form which consists of FirstName, LastName etc. Do we need a ViewModel for this scenario. I mean all I have to do is to take all the input values from TextBox and create a Customer object and then save it to the database. Why should I bother creating a ViewModel for this scenario?
First of all, that is not the main purpose of MVVM, to "mirror" everything. The View should provide the means for a user input, and certainly not process calls to any of the database layers. The ViewModel should be a GUI-agnostic application backbone, and it definetly should handle the creating of customers.
That said, what you should do, is have a ViewModel which represents a workspace for handling customers, and not just a customer ViewModel. If you really want to save on a few objects being created, add to that workspace the possibility to create and add a new customer (not CustomerViewModel). That way, you can have a View of the workspace which has elements for each relevant/required property of the customer, and by invoking some command added to that workspace ViewModel, you could get the current values filled in those (data bound to ViewModel) View elements directly to the customer model.
Consider if you could probably drop the specific customer (and other Model) ViewModels if you refactor things a bit, it would be good practice to keep things from adhering blindly to a certain pattern without explicit cause.
Let's pretend for a second that there is no business model. The only thing you have is a view. If you were to model just that view, without any knowledge of what the data means elsewhere in the system, that is a ViewModel.
The goal of a ViewModel is to, well, model the view it backs. This is a different goal than modeling the idea of a customer in your business domain. To say you will have have one ViewModel per business entity, then, is to say you will have one view per business entity, which leads to run-of-the-mill data-focused UI.
In your particular case, think about the customer edit view. It has fields that correspond to a customer's properties, and thus seems like a natural fit for binding to a customer directly. However, where on the customer object is the "Submit" action modeled? Where is the "Cancel" action modeled? Where is it modeled that field X is an enumerated value selected from a list?
How about the password? If persisted as a binary hashed value, does the view know how to hash its text? What if the system has password strength requirements?
The ViewModel is the mortar between the business model and the UI. It takes concerns from one and translates them into terms of the other. It is the point at which all the above issues are addressed. To say a ViewModel isn't necessary is to ignore its necessity.
You don't need to have a separate ViewModel for Add, you only need a single ViewModel which should do Edit and Add scenarios. If you can delete the record from the edit page than that ViewModel should also have the ability to delete. Your ViewModel should reflect the functionality your View exposes regardless of data.
I think you should reconsider having a single ViewModel for each model. I like to think of ViewModels as normalizing behavior inserted of data. By having a ViewModel for each Model class you will run into architecture issues sooner or later. I look at the application from top down overview, what is my UI trying to accomplish and from there I will get to the ViewModel and eventually I will get to my DataFactory and how the ViewModel maps down to data is almost always not 1 to 1 except for the most simplistic Views. If you try to map 1 to 1 you will have bad UI or your data will not be normalized very well.
The Stack we have here is:
View
ViewModel (Controls everything the user can do in the view, wraps properties from our POCO's)
DataFactory (Maps our POCO's to Entity Framework objects and CRUD)
POCO's (Business Logic, all rules and validation)
Entity Framework (Model, Data Access)
One note here is that ViewModel contains properties from multiple POCO's!
We inject the DataFactory through StructureMap and Unit test with xUnit along with Moq.
To answer you second question I would create a separate view only view to drop in as a user control. But you should still have a CRUD ViewModel in you app that encapsulate all that functionality in a user friendly way.
Thanks.
One reason for this VM abstraction is for testability. Another reason why you want a ViewModel is because it's basically a Data Transfer Object that might be a combination of fields from multiple models in a single container that is more relevant to your current view. Yet another reason to have VM is to take advantage of WPF two ways binding capabilities.
Using your regular model (plain POCO), you can update the View when your model change, but since your model does not implement dependency properties (most likely), you won't be able to take advantage of updating your model when the value in WPF control changes. Which mean you have to manual add a handler and do the copy this value from this control back to the model kind of thing.

Advisable approach for nested lists for binding in WPF

Question: What would be the most effective way of doing a nested list which allows for data binding in the view and awareness of what shipment is selected so that command bindings from the view can function in the viewmodel on the appropriate item in any of the nested lists?
Info:
I've got a program that I've been working a lot on to get an understanding of WPF and MVVM. But now I'm kind of stuck. It is an inventory program. People will use it when shipment come in to enter the data. A shipment has a collection of pallets, and pallets have collections of products.
So I was wondering what would be the most advisable way of going about this? I've considered having the allshipments class have a collection of shipments, the shipment class have a list of pallets, and the pallet class have a collection of products. But I can't seem to get the binding to work for through that for some reason. Another approach I've consider is having my all shipments class have a list of shipments, pallets, and products, and my view only pulls up associated pallets to the shipment of interest, and associated products to the pallet of interest, but that doesn't seem like MVVM, and and the logistics of doing all the property changed notification is already making my head spin.
Definitely go with "the allshipments class have a collection of shipments, the shipment class have a list of pallets, and the pallet class have a collection of products".
Follow this blog to get your bindings working
Rob Fonseca-Ensor is right, use the first variant. Maybe you should use ObservableCollection instead of List to make bindings work?

Resources