I'm been experimenting with the oft-mentioned MVVM pattern and I've been having a hard time defining clear boundaries in some cases. In my application, I have a dialog that allows me to create a Connection to a Controller. There is a ViewModel class for the dialog, which is simple enough. However, the dialog also hosts an additional control (chosen by a ContentTemplateSelector), which varies depending on the particular type of Controller that's being connected. This control has its own ViewModel.
The issue I'm encountering is that, when I close the dialog by pressing OK, I need to actually create the requested connection, which requires information captured in the inner Controller-specific ViewModel class. It's tempting to simply have all of the Controller-specific ViewModel classes implement a common interface that constructs the connection, but should the inner ViewModel really be in charge of this construction?
My general question is: are there are any generally-accepted design patterns for how ViewModels should interact with eachother, particularly when a 'parent' VM needs help from a 'child' VM in order to know what to do?
EDIT:
I did come up with a design that's a bit cleaner than I was originally thinking, but I'm still not sure if it's the 'right' way to do this. I have some back-end services that allow a ContentTemplateSelector to look at a Controller instance and pseudo-magically find a control to display for the connection builder. What was bugging me about this is that my top-level ViewModel would have to look at the DataContext for the generated control and cast it to an appropriate interface, which seems like a bad idea (why should the View's DataContext have anything to do with creating the connection?)
I wound up with something like this (simplifying):
public interface IController
{
IControllerConnectionBuilder CreateConnectionBuilder();
}
public interface IControllerConnectionBuilder
{
ControllerConnection BuildConnection();
}
I have my inner ViewModel class implement IControllerConnectionBuilder and the Controller returns the inner ViewModel. The top-level ViewModel then visualizes this IControllerConnectionBuilder (via the pseudo-magical mechanism). It still bothers me a little that it's my inner ViewModel performing the building, but at least now my top-level ViewModel doesn't have to know about the dirty details (it doesn't even know or care that the visualized control is using a ViewModel).
I welcome additional thoughts if there are ways to clean this up further. It's still not clear to me how much responsibility it's 'okay' for the ViewModel to have.
An option which works well for interaction between viewmodels is to bind directly to observer classes sitting between the viewmodel classes.
I think you want to make your top-level ViewModel aware of the existence of the NestedViewModel, it makes sense from a hierarchical standpoint, the master view contains the child view.
In my opinion, your instinct is right, it doesn't feel correct for the nested ViewModel to expose behaviours which are initiated by user actions on the top-level. Instead, the top-level ViewModel should be providing behaviors for the view it is associated with.
But I'd consider moving responsibility for connection construction into an ICommand, and exposing this command via your top-level ViewModel. The OK button on your master dialog you would then bind to this command, and the command would just delegate to the top-level ViewModel, for example, call ViewModel.CreateConnection() when it is executed.
The responsibility of your nested control is then purely collecting and exposing the data to its NestedViewModel, for consumption by the containing ViewModel, and it is theoretically more re-usable in different contexts that require the same information to be entered (if any) - let's say you wanted to re-use it for editing already-created connections.
The only wrinkle would be if the different types of NestedViewModel expose a radically different set of data.
For example, one exposes HostName and Port as properties, and another exposes UserName and Password.
In which case you may need to do some infrastructural work to have your top-level ViewModel.CreateConnection() still work in a clean manner. Although if you have a small amount of nested control types, it may not be worth the effort, and a simple NestedViewModel type-check and cast may suffice.
Does this sound viable?
I recently experimented with Unity (Microsoft Enterprise library) to use dependency injection. That might be a route to go when using interfaces that completely define what both viewmodels need to no from each other. MEF would be another option for dependency injection I'm aware of.
HTH
Related
Still feeling my way through MVVM, and have come up against this issue:
I have a top level ViewModel, lets call it ModelLevel1.
I have a sub ViewModel that belongs to it, that a control uses for all its bindings, lets call that ControlViewModel1. The Control only binds to ControlViewModel1.
In the Top level Viewmodel, there is a Repository, and a method to get a record from the repository from an id.
What is the best way to allow ControlViewModel1 to access the method so it can get a record from the repository?
Cheers,
Rob
Following the Single Responsibility Principle extract the logic of getting the record to a class that knows how to do it and inject that dependency to both ViewModels.
This approach can be reused by other classes, can be easily tested and is performant (unlike the aggregated events proposal).
What is the best way to allow ControlViewModel1 to access the method so it can get a record from the repository?
IMHO Controls are self contained units which have dependency properties which serve the function of a VM; hence no VM is needed.
Create a Dependency property on the control which takes in the target VM and hence has access to the method.
Create a static property on the app which will contain the VM in question and access it as a static call.
MVVM is simply a separation of concerns, remember Xaml ultimately gets compiled into C# code which is executed along side the code. Whatever process you use in code to access methods and objects can also be carried over to control instances on the page.
I have a little app with a overview of some items (entries). The title of the entry at the list in the overview is a property of the entry.
When I click an entry a kind of tab should open where I can edit the entry. When I edit and save the entry, the overview tab should update the next time.
Here a mockup for better understanding.
App is based on MVVM pattern. Each View has a ViewModel as DataContext. Each ViewModel uses a Model and each Model has a Database.
The overview tab have it's own View, ViewModel and Model (pair). Also the tabs. Each tab for entries use the same pair (singleton instance). Only a few bindings are updated If a other tab is selected.
My question is how to communicate between the tabs.
I have two approaches
Mediator Pattern (Bootstrapper combines two ViewModels with a mediator)
Each Model uses the same Database (Models listen to Database, ViewModel listen to Model)
But I dont' feel well with these approaches.
Should I communicate between Models or between ViewModels? Or is this the wrong way?
UPDATE
I really appreciate all of your answers. In my opinion none of them are wrong or right. I think it's a matter of taste which solution is right for one is. I really like the EventAggregator pattern. Here is a nice video from Karl Shifflett about the implementation of the EventAggregator pattern in PRISM. But it also explains the pattern itself.
#Thomas In my opinion it is a bad solution to do this in one ViewModel. ViewModels have to be separated. MVVM based on Separation of Concerns.
Mediator is a step in a right direction but an Event Aggregator is much more flexible. You can find dozen of implementations. For example, Prism has a ready-to-use implementation.
Communication is between ViewModels. ViewModels register themselves for notifications in the Aggregator and raise notifications on the Aggregator.
You should communicate between ViewModels, if the functionality is related to formatting Model data for display. If your are communicating data from one Model to another, then communicate between Models.
Here is a concrete example: The Microsoft.Practices.Prism namespace, which you can access with NuGet right in Visual Studio, includes a class called CompositePresentationEvent<T>, along with an EventAggregator class which does the actual communicating.
Someplace common to your entire application (I chose App.xaml.vb, but it can be any publicly scoped code file, and it works as well for C# as for VB), you define events by inheriting from that class, and supplying the type T which corresponds to the data you're sending. For example, if you want to send a message that contains a simple string, then declare:
Public Class MyEvent: Inherits CompositePresentationEvent(Of String) : End Class
In your Application class, you define an event aggregator:
Public Shared ReadOnly AppEventAggregator As IEventAggregator = New EventAggregator()
Those two items together give you the means to trade events between any two objects in your application.
This gives your entire application access to an event called MyEvent. Wherever you want to send the MyEvent message, you call its shared Publish(String) method:
Application.AppEventAggregator.GetEvent(Of MyEvent).Publish("This is my event message")
Then, to receive the event, you implement a private read-only field in the class where the event should land, something like:
Private ReadOnly MyEventToken As SubscriptionToken =
Application.AppEventAggregator.GetEvent(Of MyEvent).Subscribe(Sub(eventMessage) DoSomethingWithTheString(EventMessage))
...where DoSomethingWithTheString(eventMessage As String) would be where you process your event.
There's (a lot) more to Prism, of course, but never a need to use more of it than you need, and, as others have pointed out, lots of other MVVM frameworks with similar approaches to solving the same problem.
For me, it's usually a bad sign when I have to program for communication between view models. Sometimes, you have to make communication between view and view model, but the need for connecting two view models seems to always result in combining two view models if possible.
With your mockup, I felt the same bad feeling. Why do you have to have separate view models for tabs in first place? In your case, views can be separate but I don't see any benefit from separating view models. Thus, combining the two view models into one is my recommendation.
Maybe this Post is interesting for you, it Describe a Pattern for a Communication on Type basis. It allows you to Communicate between everything you want, without dependences between them
I have a main window, which has four user controls on it. These five entities need to communicate with each other. Is there an established method for passing values and objects between UserControls?
Edit: I'm familiar with MVVM, but I am asking for solutions outside of that paradigm.
There are a lot of ways and it depends on what you actual scenario is. The most straight forward one would be to expose public properties and/or events in your UserControls. This is the preferred way if you want to get view specific data across. If your the communication is more model related you should go the route through your ViewModel (and use MVVM).
Generally I think UserControls accessing each other directly is a strong hint toward desgin smell. It is very likely that there is a better aproach for you concrete scenario (Mediator, Eventaggregator, Controller or just the parent control).
You can communicate five entities using making delegates.
I think you need to decide upon domain model according to your project requirement and then create classes which represent entities in your model. Then pass objects of this entities as required.
There are many ways, one is to use events. There are no "direct" methods, you need to route your values through a form or a model class.
There is an established pattern called MVVM (just google for it) that has a unified way of communicating between different contols, databases, web services, calculations etc. MVVM is not a pattern for communicating between different controls, it is a much larger pattern, but it solves that part too.
I am building an application that is based on MVVM-Light. I am in the need of creating multiple instances of the same View, and each one should bind to its own ViewModel.
The default ViewModelLocator implements ViewModels as singletons, therefore different instances of the same View will bind to the same ViewModel.
I could create the ViewModel in the VMLocator as a non-static object (as simple as returning new VM()...), but that would only partially help me.
In fact, I still need to keep track of the opened windows. Nevertheless, each window might open several other windows (of a different kind, though). In this situation I might need to execute some operation on the parent View and all its children. For example before closing the View P, I might want to close all its children (view C1, view C2, etc.).
Hence, is there any simple and easy way to achieve this? Or is there any best practice you would advice me to follow?
Thanks in advance for your precious help.
Cheers,
Gianluca.
There is no obligation to store the ViewModels as singletons in the ViewModelLocator, but it certainly makes them easier to find if the view is a singleton too. Obviously, if you have multiple instances of the same View class, you will have multiple instances of the same ViewModel class, and it cannot be a singleton anymore.
To keep track of the multiple instances of the ViewModel, you can implement a dictionary in the ViewModelLocator that looks up for a ViewModel according to a key. The key can be a unique ID for the view, for example. Once you get hold of the view, retrieve its key and then retrieve the viewmodel from the locator.
Update: Often you don't even need to track multiple viewmodels. For instance, you can have the Messenger class send a message to all instances of a given viewmodel class using the Send overload. So before implementing a dictionary to keep track of the VMs, ask yourself if you really need it! ;)
Hope that helps,
Laurent
I used the naming system of the unity container.
See "How to distinguish multiple view/view model pairs using unity container".
I had a problem posted and solved in this SO question. It turned out to be very much related to Mr Bugnion's answer here (which helped me tremendously, thank you!)
What I've found is you don't need to store the view-model property in ViewModelLocator at all. Just use ServiceLocator to create an instance with a key, and in your "Dialog Service", pass the key to ShowDialog<T>(string key = null).
Also, as mentioned in this thread already, use method Messenger.Default.Send and remember to call viewModel.Cleanup() afterwards to unregister the view-model from Messenger, thereby preventing phantom view-models from trying to process future messages sent to all instances of the view-model class type.
I’m trying to use the MVP pattern and I’m running into a design problem. I’m developing an application that will have several UserControls. The UserControls themselves have nothing to do with one another and only represent a subset of the actual model. From what I’ve read, people tend to say you should use one Presenter per View. This seems to make sense, but if I have 30 UserControls, do I really want 30 Presenters? On the flip side, if I have 1 Presenter and 1 View that represent the entire “application” view, then I’ll have bloated View and Presenter interfaces. Then each View would have to implement methods that have nothing to do with it. My question is, is there a better way to handle multiple UserControls, or should I just create 1 Presenter for each View?
You should be doing one presenter per one control because of:
that would allow you to have focused unit tests tackling only that control
increased maintainability due to the fact you won’t need to support gigantic presenter containing union of presentation logic of all controls
that would prevent redundancy in cases of having same control on multiple pages
Increases SRP by having controls focusing on their specific logic while the page performs container specific roles:
There are two problems usually mentioned related to the decision “presenter per control”:
Shared context is problem where due to the fact that all of the controls are just showing different pieces of the same page data context, that situation may look like a problematic use case leading to a lot of data retrieval redundant code in every of the controls.
That is easily solvable through dependency injection where page (or controller) performs single data retrieval and then inject the data context object into every of the presenters\views (usually implementing some interface enabling that).
In case of MV-VM pattern (Silverlight, WPF) same effect can be achieved through data bounding where the page would set its DataContext which would then be used from views itself
Communication between views on the same page is second problem which is easily solvable using couple of approaches:
Controls are publishing events to which page subscribes and then makes direct calls to appropriate methods in other controls (page is container to all controls meaning it is aware of all of their members)
Observer design pattern
Event aggregator pattern
In each one of this approaches controls are communicating with each other without being aware of each other
It would make more sense to group the code that is related in one object. So, in this case, if the views are specific groupings of related code, then the presenter would also mimic these groupings. To have a "global" presenter for different views would group unrelated code in one object. It would definitely bloat the interface for the presenter as well. Check out the single responsibility principle.
Now, you could have one Presenter Manager class perhaps that could give you access to each presenter interface, like the Interface Segregation Principle states, by either inheritance (have a global concrete presenter that implements many presenter interfaces..which kind of violates the single responsibilty) or aggregation (having individual presenters for each interface and get functions...thus the global interface would the the get functions) or a combination of both (global presenter being somewhat of an adapter).
I think the best solution though would just to have 30 different presenters.
Each View doesn't have to implement the same interface... Why not define the interfaces for each control, and have one Presenter for the entire screen that contains all the controls? The Presenter can "wire up" the events on each view according to what interface defined events each view requires, to appropriate event handlers on the Presenter (and on a controller if you are doing MVPC). You may also need another interface to represent the Presenter functionality that ALL view need access to in common...
If you're doing MVPC then view events that affect the Model wopuld be "handled" in the Controller, whereas View events that only affect other parts of the View would be handled on the Presenter.
Old question, but I'm going to pipe up and have to disagree with the other answers:
you don't want one presenter per UserControl, any more than you want a unit test on every UserControl - that would be a blind misuse of a design pattern.
A UserControl is not a View.
Each logical area of your application should have one presenter; how each is broken up - how many controls, what shows what - is solely a concern of composition.