Interaction of view models in MVVM - wpf

I have a WPF application which follows the MVVM pattern. The application defines two views and view models so far:
LoginView(Model)
ProjectsView(Model)
Both view models need to access several properties from other view models.
Example:
LoginViewModel has a property ProjectList. ProjectsViewModel needs to access this property as well.
This is only a simple example. Later there will be several UserControls which all need to interact with each other.
Would it be a better idea to create one huge view model which all UserControls (views) set as their DataContext? If not, how can all the different view models interact with each other?
Remark:
This question is closely related to this one but with a different approach.

You should definitely not make a huge "main view model" -- this is an anti-pattern not dissimilar to a god object.
The key idea here is that your viewmodels do not need to access several properties from other view models; rather, all of the viewmodels need to access specific pieces of information.
Right now you are most likely injecting this information into each viewmodel at the time of instantiation. Instead of doing this, provide each viewmodel with a reference to a service -- an application module that exposes this information through properties and/or methods. The information can be exposed in the form of scalar values if it's extremely simple in nature, or in the form of models if it's anything more complicated than that.
Schematically this would look like
/--------------\
| ViewModelA |
| | <=======\
| | |
\--------------/ | <--- information is pulled /================\
+=========[model]===[model]====== | Service |
/--------------\ | \================/
| ViewModelB | |
| | <=======/
| |
\--------------/
The service should be injected into the viewmodels upon construction (either manually or by the DI container if you are using one). Each viewmodel should only require a reference to the service and enough information to tell to the service which model it's interested in; it will then request that model from the service and populate its "interesting" properties based on that.
This way of doing things is more involved than simply constructing a viewmodel object and setting its properties externally, but it will allow your application to grow in complexity without becoming unmanageable.
For example, if there are lots of views that bind on different viewmodels and these viewmodels depend in complex ways on a number of models, a sane manner to work would be:
A view/viewmodel pair is constructed
The viewmodel requests any models it needs to know about from the service; it subscribes to an event that the service exposes to let subscribers know that a model has changed
Changes are performed to the models through databound controls
The view invokes a "save" command on the viewmodel
In response to that, the viewmodel invokes a "save this model" method on the service
The service persists the information and publishes a "model changed" event (see step 2)
Other viewmodels interested in the same model know that the model has changed and can query the service for its new state
This is possible if everything is routed through the service. Imagine what it would take to keep everything synchronized otherwise -- the only way to cope would be to put all the information into a giant viewmodel and reference that from everything else. Ugly.

Usually I do one of 4 things:
Make my ViewModels reference each other, and pass the property around. For example, LoginViewModel might set ProjectsViewModel.ProjectList on successful login. How you implement this depends on how your ViewModels are related to each other, and where logical points of connection would be.
Make an ApplicationViewModel which manages things like which page is current, and application-wide objects like the current user or current project list. It would handle transferring shared data to the ViewModels that needs it.
Use some kind of Event system to broadcast a message anytime an application-wide property changes, and have any ViewModel that's interested subscribe to receive those messages. The message typically contains the new object as well, so anyone subscribed to receive that message type has access to the new object. (I have a brief summary of Event Systems in my blog article Communication between ViewModels with MVVM if you're interested)
Depending on if any of the other options work better, I may consider creating a singleton to hold application-wide data instead. For example, if the User is set on Login and is accessed from many of my ViewModels, I may create a singleton to set the user on first login, and then all my ViewModels can access it.
The one thing I would not do is make one big ViewModel holding all available data. ViewModels should only contain the data specific to it.

If you are using some sort of dependency injection tooling, you could inject a class that provides those values, for example, an IProjectService, that can return the list of projects on each of those view models.
The idea of one giant view model does not sound appealing, nor does strong coupling between view models by accessing each other's public properties. And if you want interaction between the view models, like when a project gets added, use a publish / subscribe model for each of the events you expect to occur.

Your Model should contain things like a project list, or give you the ability to access it. The ViewModel is simply meant to be a layer between the Model and View, giving you the chance to bring different Model objects together and mold them into a shape which the View can readily display and to handle commands from the View (modifying the Model in response).

Create one Base View Model keep all common Properties in that, Create singleton to BaseViewModel and add that singleton property in all View Models. All Viewmodels will get synced at one time.

Related

Reusing WPF MVVM Views

I've inherited an application which uses the view-first MVVMC patern
In the application I've created 2 step process which creates a person and assigns them to a group. To do this I've created a view and corresponding view model (all views have a 1-2-1 relationship with a view model, view models are injected into the View constructor and are registered with the Unity container using the TransientLifetimeManager) called CreatePersonMaster, the view simply contains a region (shown by the dashed line) which sub-views can be loaded into and the view model subscribes to two loosely coupled events, "PersonCreated" and "GroupSelected". The "PersonCreated" event saves a Person entity in a field and the "GroupSelected" event takes the saved Person, creates a Group association and saves them to a database.
This view/view model doesn't do anything until the events get raised so I load the following sub views into my the region.
These views/view models fire the events which get handled by the master view.
I also have an edit view where I want to re-use the select group view.
I can do this by subscribing to the appropriate events in the EditPersonMaster view model.
My question really is, is this the appropriate way to do this? Because I'm using loosely coupled events I don't get any feedback into the sub-View/ViewModels if there's an error when creating/reassigning? I could probably fire another "ErrorBlah" event for the inner view/model to handle and update the view.
Is there another way to do this? Composite commands don't seem to fit the bill but maybe I don't understand them correctly.
Here is how I understood your question: You have persons stored in a database, which have a property/column group. In your UI, you want to create persons and assign the group property. Also, you want to be able to edit the group property of existing persons in a different region/page/master. You want to reuse the control for assigning the group. Your controls fire an event, which is handled by the Master in a way that it creates the entries in the database (is that correct?). Your question is whether this is a good approach and what alternatives you have?
I see two options:
1. Modularize your business logic:
You could inject a data service into your ViewModels, which could access the database directly. This way you can handle errors etc.. directly where they occur and don't have to pass them through the whole system. If you want to notify other modules of changes on the database (specifying the changed dataset or so), you can do so with a composite event. I think of the PRISM modules more as of complete elements, including UI and business logic and keep communication between them as little as possible.
2. Keep your business logic central and share it:
If you want to stick to your architecture, have singleton Model which is injected into the ViewModels. Manage your state in the model and have the ViewModels pick the pieces they want to provide to their view.
Hope I got he point, though...

Should I dependency inject? How do I do it?

Okay, so I am working with Microsoft Prism in WPF using a MVVMC(or MVCVM) pattern.
In my ChatModule I have a series of Views, ViewModels, and one Controller.
For the Views I have
ChatAreaView - Displays the chat messages that come in to be read. This is hosted inside of a TabControl region so that I can have chat windows between the user and other users, or maybe file transfer windows, etc.
UserAreaView - This is a list of the users. Right clicking has context menu to interact with them... like sending a file or whispering.
MessageAreaView - This is where the user types in messages to be sent to all of the others.
For each view, I have a corresponding ViewModel. ChatAreaViewModel, UserAreaViewModel and MessageAreaViewModel. These ViewModels essentially only contain properties.
For example, the UserAreaViewModel defines a struct of type User which is essentially just a Name. Actually this is defined outside of the class, but still... it uses it. It has an ObservableCollection to store a list of all the Users who are currently connected. It also has ICommand properties defined to interact with the user. Right now I have SendFile, Whisper and Nudge... with intent on adding more in the future.
The Controller creates these views and ViewModels, and marriages them. It news them up, assigns the ViewModel as the corresponding View's DataContext, and sets all the initial properties of the ViewModel. Over the lifetime of the module, it will react to user interaction and execute DelegateCommands that it has assigned to each of the ViewModel's ICommand properties. These will further alter the state of the properties in a ViewModel.
I am using the actual types of Views and ViewModels, instead of interfaces, like such.
#region Views
ChatAreaView viewChatArea;
UserListView viewUserArea;
MessageView viewMessageArea;
LoginPromptView viewLoginPrompt;
#endregion
#region ViewModels
ChatAreaViewModel viewModelChatArea;
UserAreaViewModel viewModelUserArea;
MessageAreaViewModel viewModelMessageArea;
LoginPromptViewModel viewModelLoginPrompt;
#endregion
Would things be a lot more neat, less coupled if I defined interfaces for the Views and ViewModels, and operated on these interfaces within the controller instead of the concrete implementations? Could I then just register them with my Container in the Module class(which is essentially the root of each Module)?
What do I have to gain from doing this? How would I implement an interface for each view to distinguish them from the others? They don't really do ANYTHING except have XAML... and teh ViewModel's don't really do anything either except have certain properties. And those properties might be subject to change. On the UserAreaViewModel for instance, I will definitely want to add more commands so a user can interact with another user in different ways.
Can somebody help me out here? In my mind I'm thinking I should be abstracting this stuff, but I don't really know a logical way I should be going about it, or even if it's a wise idea to do so. What do I have to gain?
Thank you for your time. The below image is an example of what I'm working on. Ignore the Add new Item button and the styling of everything... that's not what I'm working on right now.
loosely coupled - can replace an entire class with altogether different implementation in future.
independent development.. can inject a dummy UI / view until final UI gets ready. two pieces can evolve at the same time (after having a common contract).
no need to add references to the modules (implementing the view). can use ConfigurationModuleCatalog to discover types from config file.

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).

MVVM, should I put logic in model or view-model (controller)

I am new to MVVM and now doing some MVVM refactorying work on a silverlight project, suppose it is a book shopping application.
The View is a book list, I bind the title of the books to the ViewModel. So I have a public string Title { get; set; } in ViewModel, also a public string Title { get; set; } in Model (am I right?)
Now I want put a event handler to update the book title, should I put the event handler in ViewModel or Model? and what is the Model used for?
In my opinion "Neither"... Add controller classes to the mix of MVVM instead.
The problem with putting controller code in view models is that is makes them harder to test independantly. In many ways I see this as just as bad as code behind.
It seems to me that everyone assumes MVVM has no controllers as they left out the C. MVVM is really a variation of MVC "that just adds ViewModels".
Maybe it should have been called MVCVM instead?
ViewModels are only there to offload the "GUI" code from the view and to contain any data for binding. ViewModels should not do any processing. A good test is that your ViewModel is testable via automated unit tests and has no dependencies on data sources etc. They should have no idea where the data is actually coming from (or who is displaying it).
Although it can be overlooked/avoided, a Controller should be responsible for deciding what data model to display and in which views. The ViewModel is a bridge between Models (the M in MVVM) and Views. This allows simpler "separated" XAML authoring.
The pattern we are using successfully on all recent projects is to register controllers only, in modules, and initialise them at startup. The controllers are very light/slim and the only thing that needs to hang around for the life of the app listening for, or sending, messages. In their initialise methods they then register anything they need to own (views and viewmodels etc). This lightweight logic-only-in-memory pattern makes for slimmer apps too (e.g. better for WP7).
The basic rules we follow are:
Controllers make decisions based on events
Controllers fetch data and place it in appropriate View Model properties
Controllers set ICommand properties of View Models to intercept
events
Controllers make views appear (if not implied elsewhere)
View Models are "dumb". They hold data for binding and nothing else
Views know they display a certain shape of data, but have no idea
where it comes from
The last two points are the ones you should never break or separation of concerns goes out the window.
In simplest terms, the Model is the 'real' underlying data model - containing all the info for the booklist that might be needed by the application, able to get and set data from your database.
The ViewModel is an object that exists primarily to provide data binding for your View. It might be a subset of the Model, or it might combine properties from multiple Models into a single object. It should contain the necessary and sufficient properties to allow the View to do its job.
If the event handler relates to the View, then it belongs in the ViewModel. You might try using the Command Pattern (see Custom WPF command pattern example) if it fits your purpose.

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