ViewModels talking to each other - mvvm

I've just created my first c# / XAML application using mvvmlight and I've tried to implement the MVVM pattern as best I can (WP8 app). However, I've slowly morphed my code in to a certain style and I don't think its correctly implementing the pattern! Any advice on how things are supposed to be would help enormously.
For example, using mvvmlight I am making heavy use of the ViewModelLocator. Some of my viewmodels get created right away, like the SettingsViewModel (there is a SettingsView).
SimpleIoc.Default.Register<SettingsViewModel>(true);
And then elsewhere in my project, my other viewmodels will directly access this viewmodel for occasional information via a property or a method... like this;
mySetting = ViewModelLocator.SettingsStatic.GetSomeSetting(var);
My concern is that my viewmodels are talking to each other in this way more and more. The issue with this is that they probably can't be tested independently now because they require or assume the existence of other viewmodels.
Any pointers here would be great!
EDIT: Another example is having a PersonView, and the PersonViewModel has some helper methods for UI display. In some cases I have other views that need to display this info.... and I use the viewmodellocator to get to them, rather than writing the helper methods again in the current viewmodel.

You are right in thinking that viewmodels being dependent on viewmodels is going to cause trouble. When I need to have access to "global" settings in my app, I use an interface that can be injected in the constructor of the view model. So, You can create an ISettingsService that contains the properties and methods you need. You also create a design time setting service that mimics or fakes the data/properties of the ISettingsService Interface
then in your view model locator you use this:
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<ISettingsService, DesignSettingService>();
} else {
SimpleIoc.Default.Register<ISettingService, SettingService>();
}
Create the DesignSettingService and SettingService which both implement the ISettingsService.
As for you vewmodels, the SimpleIOC will resolve/inject the required elements passed into the constructor of the class. If you have a class/viewmodel called MyViewModel and it wanted to use the settingsservice then you would define the constructor like this:
private ISettingsService _SettingsAccess;
public New(ISettingsService SettingsService)
{
_SettingsAccess = SettingsService;
SettingProperty= _SettingsAccess.GetProperty;
}
This keeps the viewmodels decoupled as this service is resolved in the constructor, that way you can change the implementation of your ISettingsService without breaking every viewmodel that uses it.
I use a INavigationService to handle all the navigation events in my app, this allows me to cancel navigation based on another viewmodels properties without needing the other viewmodel to be directly called/referenced by the current one.
One view model should never directly call another view model. Using this method you can pass as many "services" as are needed to the viewmodel. Every viewmodel I use gets a dataservice that connects to my model in addition to the navigationservice. Ie. A viewmodel that deals with people gets an IPeopleDataService where this service contains all the CRUD operations that affect the database. That way I can change the people objects in the database and service functions without having to change the people viewmodel as well.
I hope this helps.

Related

MVVM and Multi-threading

We are using Avalonia and ReactiveUI but have run into an issue. Our Model will be updated by an asynchronous thread and we're trying to figure out how to tie it (bind it) correctly to the View. It seems in the MVVM way of thinking the View doesn't interact directly with the Model, only the ViewModel. So do we need a double binding where the ViewModel binds to the Model and the View binds to ViewModel? If so how can this be done?
As a first try our Model inherits from INotifyPropertyChanged and our ViewModel subscribes to it's PropertyChanged event. However, we have to manually add code to switch between all of the possible properties of our Model to update our ViewModels correct property (and thus the View using this.RaiseAndSetIfChanged). It seems like there should be a better way...
Please, excuse the simple question but we are new to MVVM.

GWT: MVP Presenter Interface

I try to understand how the gwt example about activities and places works (https://developers.google.com/web-toolkit/doc/latest/DevGuideMvpActivitiesAndPlaces). I am wondering why they define an interface for the presenter. I know the view interface is helpful to exchange the view easily. But what's the use of the presenter interface?
Its always a best practice to design application with interfaces rather than concrete classes.
Reference - What does "program to interfaces, not implementations" mean?
Reference - WikiPedia example for MVP
Another key factor in MVP architecture to make your design pretty clean is defining an Presenter interface(As we already know the beauty of interface OOP conceptin JAVA).
Presenter interface that allows our View to callback into the presenter when it receives an event. The Presenter interface defines the following:
public interface Presenter<T> {
void onAddButtonClicked();
}
And then you can set the presenter to your view like below
private Presenter<T> presenter;
public void setPresenter(Presenter<T> presenter) {
this.presenter = presenter;
}
Finally when your PresenterConcreteClass implements your presenter interface those implementations will triggers.
Besides the cleanliness of using an interface, there's also no reason you wouldn't test your view. You could use end-to-end tests, but you can also simply use a GWTTestCase where you instantiate the view and use a mock presenter.
You'd then be able to test that “when I click on this button, it should call this method from the presenter with the values X, Y and Z as arguments”, or “when I call this method of the view with those arguments, then such widget should turn red and that other one should hide/collapse/show/whatever”.
I've also used it, once, to similarly build a simple testbed app to manually test the UI with fake data. The app consisted of buttons to simulate the presenter calling the view with fake data, and handled the presenter calls back from the view with Window.alert or similar things. You'd launch the app in your browser and click here and there and validate that the view works as expected.
This can be useful when you later add a field to your form, to make sure you correctly wire it with the presenter. You don't want to setup your GWT-RPC/RequestFactory/whatever services from the real presenter, when a unit-test could be enough.
2 big reasons off the top of my head (there may be others too...)
Testing: Your Presenter then does not have to have a direct reference to the View, which is nice because the View contains GWT Objects (i.e: any Widget) which cannot be used in a standard Unit Test Case: Any GWT Object must have a JS container (i.e: Browser, or GWTTestCase) to be instantiated; A JUnit test case cannot use a Browser; GWTTestCase runs VERY slow, so you should prefer not to have to use it. Without the interface, the Presenter would have to reference the View's methods by a direct reference to the View; that means when testing the Presenter, you must instantiate the View, which must instantiate its Widgets (which at that point require the GWTTestCase for the Widgets). And all you should be aiming to do in the 1st place is to test the logic, which should be completely in the Presenter to avoid GWTTestCase... With the Display interface, you can do just that: Focus on testing the Presenter, without the complication of instantiating the View (which has its own degree of instantation complication) and messing around then necessarily with GWTTestCase
Have multiple Views for the same Presenter: [I think you would only ever do this if you have different platforms (i.e: mobile App vs. browser) which each require their own View (since a mobile App version of the View is rendered differently from a browser View, since they are different platforms with different GUI entities)]. The multiple Views would then all just implement the Display interface in their separate ways. Then the single Presenter can contain the logic that is the same for all Views, be used for all the different Views, and all View implementations are guaranteed to follow the same expectations (which are the codification in the Display interface) of that single Presenter! This is a manifestation of the OOP best practice of designing with interfaces, which #SSR Answers.

MVVM + Implementation of View specific functionalities called by the ViewModel

here is my "problem" I want to resolve:
I have got many "View only" specific functionalities for example:
Change the ResourcesDictionary of a View at runtime (for changing skins from black to blue or whatever)
Save and restore View specific settings like the view size, or grid properties set by a user
...
All those functionalities have nothing to do with the ViewModel, since they are really view specific and might only fit to one client (View) of a ViewModel (in the case a ViewModel has got more than one client). The examples above are only two of a large amount of functionalities I want to implement, so I need a more generic solution instead of solutions that only fit those two examples.
When thinking of a solution I came two the following approaches
Create a ViewBase that inherits from DependancyObject. I dont like this solution because it somehow breaks the idea of the MVVM pattern where a View has no code behind. And to call this methods I somehow need to reference the View in my ViewModel which also negates the idea of seperation of concerns.
Create an IView interface. As dirty as the first approach. Each View needs to implement IView and therfor has code behind. Also the ViewModel needs to "somehow" know the IView implementation to call its methods
Bind Properties of the ViewModel to Triggers, Behaviours, Commands of the View. This approach seems to be the best, but I think I will run in a limitation of usage very fast because some functionalities might not work with this approach. For example just Binding a resourceDictionary to a View might not work because a merge is needed for correct display of new resources. Then again...I have view only specific functionalities / informations (like a resourcesdictionary) in the ViewModel, but only a specific client of the ViewModel uses this property.
If anyone of you already had the same problem and got a smart/smooth (and mostly generic ;) ) solution for my problem, this would be great.
Thank you
The easiest way to do that without introducing coupling between the View and ViewModel is to use a Messenger (also called Mediator in some frameworks). The ViewModel simply broadcasts a "change theme" message, and the View subscribes to that message. Using the Messenger class from MVVM Light, you could do something along those lines:
Message definition
public class ThemeChangeMessage
{
private readonly string _themeName;
public ThemeChangeMessage(string themeName)
{
_themeName = themeName;
}
public string ThemeName { get { return _themeName; } }
}
ViewModel
Messenger.Default.Send(new ThemeChangeMessage("TheNewTheme");
View code-behind
public MyView()
{
InitializeComponent();
Messenger.Defaut.Register<ThemeChangeMessage>(ChangeTheme);
}
private void ChangeTheme(ThemeChangeMessage msg)
{
ApplyNewTheme(msg.ThemeName);
}
I've long since adopted the way of thinking that Patterns were made for Man, not Man for patterns. Quite often you'll see a situation where MVVM doesn't fit and to resolve it, very smart people have come up with ways to get around it, while maintaining the pure MVVM look.
However, if you subscribe to my school of thought, or if you just like to keep it simple, another way is to allow the ViewModel to reference the view; via an interface of course, or that would just be terrible programming practice. Now the question becomes, how to get the view into the viewmodel?
the simplest way would be to do this in the view's dataContextChanged event. However if you want to try something different, how about using an attached property or dependency property to inject the view into the viewmodel?
I've successfully used this techniques on a number of WPF projects and don't feel dirty or somehow compromised. I call it MiVVM or Model Interface-to-View ViewModel.
The pattern is simple. Your Usercontrol should have an interface, call it IMyView. Then in the ViewModel you have a property with a setter of type IMyView, say
public IMyView InjectedView { set { _injectedView = value; } }
Then in the view you create a dependency property called This
public MyUserControl : IMyView
{
public static readonly DependencyProperty ThisProperty =
DependencyProperty.Register("This", typeof(IMyView), typeof(MyUserControl));
public MyUserControl()
{
SetValue(ThisProperty, this);
}
public IMyView This { get { return GetValue(ThisProperty); } set { /* do nothing */ } }
}
finally in Xaml you can inject the view directly into the ViewModel using binding
<MyUserControl This="{Binding InjectedView, Mode=OneWayToSource}"/>
Try it out! I've used this pattern many times and you get an interface to the view injected once on startup. This means you maintain separation (Viewmodel can be tested as IView can be mocked), yet you get around the lack of binding support in many third party controls. Plus, its fast. Did you know binding uses reflection?
There's a demo project showcasing this pattern on this blog link. I'd advocate trying out the Attached Property implementation of MiVVM if you are using a third party control that you cannot modify.
Finally may I suggest to find the best tool for the job is almost always the best programming approach. If you set out to right "clean" or "correct" code you are often going to hit a wall where you need to change your approach throughout.
When you said
I have got many "View only" specific functionalities for example:
that makes me think that you are mixing the "What" and the "How". I'll explain what I mean by this.
The what is your app requirements:
Change skin color of app
Save & Restore
Size
Grid properties
I argue that the above has everything to do with your ViewModel, your VM should contain simple or complex properties that can tell your View what it wants to do e.g.
public class SettingsViewModel
{
public Color Skin { get;set;}
public Size ViewSize {get;set;}
public GridProperties GridProperties {get;set;}
public void Save() {//TODO:Add code}
public void Restore() {//TODO:Add code}
}
your View would bind to that ViewModel and implement the "How".
If you're creating a web app then the how will take the ViewModel and create html. If you're using WPF you bind to those properties in XAML and create your UI(which might cause you to switch out ResourceDictionaries etc.)
Another thing that helped me out is to realize the asymmetrical relationship between the View and the ViewModel. In it's purest form the ViewModel should know nothing of the View, but the View should know everything it needs to know about the ViewModel.
That's the whole point behind separation of concerns.
Responses to your "solutions":
Your first option violates MVVM principles, have you read this article?
I believe this article will help you come to terms with view selection based on the ViewModel.
I don't know of what "limitations" you will come across, but WPF is quite robust and there will be solutions available.
I agree that View specific functionality should stay in the View (Save and Restore the window size, set focus to a specific control, etc.).
But I don’t agree that the introduction of an IView interface is ‘dirty’. That’s a common design pattern called Separated Interface which is described in Martin Fowler’s book Patterns of Enterprise Application Architecture. Furthermore, code-behind is not ‘evil’ as long the code relates to View specific functionalities. Unfortunately, that’s a common misunderstanding in the MVVM community.
If you give the introducing of an IView interface approach a change then you might find the WPF Application Framework (WAF) interesting. It solves our issues through this interface. You are going to see this in the sample applications.

Should I register ViewModels in Container?

Should I register ViewModels in Container and resolve from there?
Benefits:
I can perform some actions when view model is activated
Container will inject dependencies for me
???
Drawbacks:
ViewModel lifetime management can be tricky:
if I make ViewModel singleton then I can't instantiate several controls of the same type
if I make ViewModel transient then I can easily end up in a situation of having several different instances when I actually expect same instance injected
???
What's the right answer?
I'd prefer to register if I could mitigate lifetime drawback.
I'm using Caliburn and Autofac if it matters.
A container is an ecosystem inhabited by the objects it creates. View models interact with those inhabitants and thus are also part of the ecosystem. To accurately reflect that relationship, you should register view models in the container.
You should always use InstancePerDependency with view models. A view model represents the state and behavior of a particular piece of UI - it is the non-framework-specific analogue of a control. Just as you can't generally place the same control instance in two locations in a UI tree, you can't also reuse the same view model instance.
If you could, we'd call it a ViewsModel :-)
The benefits of 2) is enough for me to let the container handle viewmodels. We're using our own MVVM framework where there is a strict one-to-one relationship between view instances and viewmodel instances. Thus, the 1) drawbacks are non-existent.
In cases where we need to share data between views, we accomplish this by injecting the viewmodels with a shared service instance.
Except from that, are there other circumstances where you expect one viewmodel instance to be shared among several views?
Not sure about autofac or Caliburn (might still apply) but when it comers to the Unity Container I will only register the ViewModel if...
I need to have it disposed of when the container is disposed of. You can create a lifetime manager that will store the newly created (non singleton) view model instance.
container.RegisterType<MyViewModel>(new DisposeableInstanceLifetimeManager());
...
container.Resolve<MyViewModel>(); // here all dependencies will get injected
...
container.Dispose();
If you want to share data I tend to create a sub (child) container and register the model as a singleton and have multiple view models share the same model.
var child = container.CreateChildContainer();
child.RegisterInstance(model, new ContainerControlledLifetimeManager());
child.Resolve<MyViewModel1>();
child.Resolve<MyViewModel2>(); // both can share the model instance
(Note: with Unity all dependencies are injected when using Resolve on the ViewModel even if it is not registered with the container).
Otherwise unless you need a singleton ViewModel (although I cannot think of when that would be useful) I feel adding the ViewModel to the container just adds more code for no benefit.

MVVM View reference to ViewModel

I'm using MVVM in a WPF app. I'm very new to both. Let me state that I am not a purist in the MVVM pattern, I am trying to use as many best practices as I can but am trying to make what I think are reasonable compromises to make it work in our environment. For example, I am not trying to achieve 0% code in my View code-behind.
I have a couple of questions about best practices.
1) I understand I don't want my VM to know about the attached View, but is it reasonable for the View to have a reference to its VM?
2) If a control in a View opens another View (such as a dialog) should I handle this in the View? It seems wrong to handle it in the VM since then the VM has some knowledge of a specific View.
1) The View has definitely a reference to the ViewModel through the DataContext. And you are allowed to cast the DataContext in your View:
public class ShellView : Window
{
…
public ShellViewModel { get { return DataContext as ShellViewModel; } }
This isn’t a violation with the Model-View-ViewModel pattern.
.
2) You are right. A ViewModel shouldn’t open another View. A better approach is to use Controllers. They are responsible for the Workflow of an application.
If you are interested in more detailed information then you might have a look at the WPF Application Framework (WAF).
1) Here are two simple practices for View's "knowing about" a ViewModel. It's reasonable for a View to know about a ViewModel (for Data Binding) -- but you may not need it in your case. See if either of these approaches help solve your problem. There are other ways, but these should be simple enough:
public View(ViewModel vm)
{
View.DataContext = vm;
}
public Bootstrapper(View v, ViewModel vm)
{
v.DataContext = vm;
//or, if you want it to have no parameters
View v = new View();
ViewModel vm = new ViewModel();
v.DataContext = vm;
}
The first option isn't bad if you have a service location tool, but there is a flavor of MVVM that doesn't like any code in the View's Code-Behind. The second option isn't bad either, should be simple enough for your task.
2.) This question can be a bit of a sticky point in MVVM design. If we are talking about a general Win32 MessageBox, I will often separate that logic into an additional object and put it in the VM. This way tends to a little more clear. (For example, I have selected an item in a ListBox, I have attached a Delete ICommand to that action, and in my ViewModel when this ICommand is Executed, I will poke my MessageBoxObject to ask if the user "wants to really delete" this item). More advanced "Dialogs" would use additional ViewModels and DataTemplates for those ViewModels. I prefer the Mediator approach.
1). The view will need a reference to the view model at some level, since the viewmodel will act as the view's datacontext.
2) One way to handle this is to have a generalized viewmodel representing a dialog, that is owned by the main viewmodel (the one being used as the views datacontext.)
You can use a command to crate a new instance of a dialog viewmodel, which will have a corresponding datatemplate defined in your resources. This template will be set to bind to the dialogviewmodel type.
Quite late, but I think this is tricky enough to deserve lots of different perspectives.
I understand I don't want my VM to know about the attached View, but
is it reasonable for the View to have a reference to its VM?
As already answered, a proper View-ViewModel arrangement involves the ViewModel being assigned as the View's DataContext property. That allows DataBindings to be "automagically" established from declarative XAML, or fine-tuned via code behind.
Sometimes, you'll be tempted to write, in your code behind, something like this:
var dc = DataContext as CleverViewModel;
CleverViewModel.CleverProperty.Add(someValue); // just a simple example
I believe the proper way to achieve this sort of things is NOT to cast DataContext, but instead:
Have some dedicated control in View, for example an ItemsControl with its ItemsSource two-way databound to some property in viewmodel:
<ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>
Cast the bound property instead of the whole ViewModel, in code behind:
var collection = (ObservableCollection<double>)cleverControl.ItemsSource;
collection.Add(someValue);
Note the important difference: the second approach in this example doesn't require the View to know the ViewModel type, it only needs a property named CleverProperty of type ObservableCollection<double>. This allows me to have polymorphic or even duck-typed ViewModels.
If a control in a View opens another View (such as a dialog) should I
handle this in the View? It seems wrong to handle it in the VM since
then the VM has some knowledge of a specific View.
This shouldn't happen in strict MVVM, and its not difficult to avoid using DataTemplates. DataTemplates map a given type of DataContext to a given type of view, so anytime the datacontext of a ContentControl changes, its display also changes, provided that you have a DataTemplate for that type:
A control in the view could send a command to the ViewModel, which in turn would update some of its own properties, that would be reflected by the view.
A View could contain another View, outside the knowledge of the ViewModel. In this case, the code behind can manipulate the datacontext of the contained view.
There are more subtleties, but I have been using this approach with good results. Hope this helps someone.
Build Your Own MVVM Framework
I found the approach suggested by Rob Eisenberg very interesting.
Key points:
Convention over configuration
ViewModel first
Which is very similar to ASP.NET MVC philosophy.
I highly recommend watching the video.