MVVM View Model Organization - wpf

Making my first WPF MVVM application and I have a question about the organization of View Models. I have a ClassA with a one to many relationship with ClassB
I want the main view to look like this. It contains some info from class A along with a listview of all Class B instances that are associated with Class A
I have come up with two approaches but I am unsure about which organization, if either, is considered the best approach. (This is a standard CRUD application: I want to be able to modify Class A, Add and remove Class B from Class A, modify Class B)
Approach 1
The main view model contains a ClassAViewModel and a List of ClassBViewModels
Approach 2
The main view model contains a ClassAViewModel. The ClassAViewModel handels its own list of ClassBViewModels
I would greatly appreciate any input on which approach will be best for me / a new approach. I'm also open to any recommendations of resources that would help me better understand software design and best practices in general

The main view model contains a ClassAViewModel and a List of ClassBViewModels
No. The ClassB view models are only needed for views of ClassB, which is not what your main view is. Your main view will have a list (ListBox or ItemsControl) of the array of ClassB in your view model and templated to a user control that knows how to display them.
That user control then has its context as ClassBViewModel (only one) and handles the rest of the responsabilities for ClassB specifically.
The main view model contains a ClassAViewModel. The ClassAViewModel handels its own list of ClassBViewModels
Again, no. At best you're confusing view models (the data necessary to display in the view your model types) and models (which correspond to the data itself). AVM links to an A, which links to a list of B, which, when bound to a view themselves, go through a BVM (if necessary).

Related

Synching a modifiable list over multiple views in MVVM

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?

Common model among multiple views

New to WPF. I have a Product model that is an L2S entity. I am creating an application in WPF to edit the product information to potentially replace an old Windows forms app I have. the application has a tab control with a number of tabs on it, such as Packaging, Marketing, Photos, Construction, etc.
My question is how do I structure this in a MVVM system. Do I have a separate view for each tab, each with it's own view model relating to it's particular subset of the Product model? Or do I have a single view with the tab control and all of the fields and a single view model to encompass the model in it's entirety? Or am I going about it completely wrong?
I feel like the first option is the way to go, but then I am also unsure of how to share the same model across multiple view models. Can anyone shed some light on this for me?
--Edit--
Examples of data on the pages:
Marketing has several text fields, and a few subset entity collections such as features, applications, and cross references.
Photos handles a collection of Photos for the product
Packaging and Construction are each a large collection of text fields/combos/checkboxes related to their respective information in the Product
With this minimum of info you've provided I would suggest following solution:
Main ProductView view
Separate View for the each tab
Main container ViewModel: ProductViewModel
For complex tabs separate view model as well. For instance you would have a separate PackagingViewModel so ProductViewModel should expose public PackagingViewModel Packaging property
ProductViewModel should accept all model-related stuff (perhaps some services, model entity, etc) and then initialize all other child view models.

What is the point of having both Model and ViewModel in M-V-VM?

I always find it tempting to put a model and a view-model together in one class, and I don't see the downside of doing that.
There must be a good reason for separating them. What am I missing?
ViewModel is the soft-copy of the View i.e. if you have a updateable ListBox on View, you will have an ObservableCollection in your ViewModel that represents that list of items in the listbox. Similarly if you have a Button on your View, the VM will hold its Command.
Model will be actually what has the data that the View shows. So the type collection in your VM is of, can be termed as a Model class.
E.g. a Employees ListView is a View, and has a data context which is the instance of EmployeeViewModel class that has an ObservableCollection property of Employee class where Employee class becomes a Model.
Usually there is 1-1 relationship between View and VM and 1-N relationship between VM and Model.
The model is the domain of your application and so contains your domain logic such as business rules and validations. The ViewModel is the model for your view. It handles the interactions between the user and the view, i.e. when the user clicks a button the view model will handle that interaction and may or may not make changes to the model. Normally in an OO language, you want your objects to have a single responsibility only.
In WPF the ViewModel usually implements the INotifyPropertyChange interface which is then observed by the view for any changes. You wouldn't want the model to implement this interface since it is not related to your domain in anyway.
Another reason for separation is that sometimes your view might not necessary show all data that is in the model. For example, if your model exposes 15 properties but in one of your view the user needs to see only 5 of those properties. If you place your model in the ViewModel the view would be exposed to all 15 properties whereas if you encapsulate the model in the ViewModel then only those 5 properties would be exposed to the View.
There are probably many more reasons but in general it is a good design principle to keep them separated. With that being said, if your application is small enough you can get get away with having your model and ViewModel together to reduce redundancy in your code.
The first real downside of doing this is a lack of separation of concerns. And soon this will lead to redundant code. Now, that said, I've seen a lot times where developers have used their Model objects as ViewModels. And if we're totally honest with ourselves, in a very thin app, separating these concepts can actually lead to more redundancy.
The best thing you can do is learn more about MVVM, and its roots in MVC and Presentation Model, but I think it's a great thing that you're asking this question and that you're not blindly following dogma. In fact, I often don't even start with MVVM at all when I begin a small app. I'll often start with a hundred lines or so in the code-behind, proving a concept, and then start refactoring it into MVVM.
More to the point of your question, the model and view-model have - in a conceptual sense - very different purposes. The Model includes your business logic (domain logic), data model (objects, attributes and relationships), and data access layer. The ViewModel is essentially an adaptor for the Model, adapting it for the specific purposes of the View. In some cases you might have 3 different views (and view-models) for a given data model object. Each view-model would be adapting those same attributes on the model object for the specific purposes of that particular view.
My simple answer (and I don't pretend to be WPF Guru) would be that , in WPF, you'd need a VM when:
1. You don't want to expose all your Model to a specific view
2. Your model is not in "WPF style" (doesn't implement INotifyPropertyChanged, no observable collections or no Commands).

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.

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.

Resources