Is it possible for the View to subscribe ViewModel CLR event? - silverlight

Sometimes a view model needs to raise notifications, that a view should handle and do something in response, esp. when these can't be modeled as properties and property change notifications.
Anything in MVVM Light that can allow the view to listen to events and translate view model notifications into user interface actions via declarative Xaml markup?

Personally I find the technique of raising events from the VM and catching them in the view acceptable in certain circumstances. I typically prefer to work with the Messenger for such occasions though, especially if you need custom event args (because it is quite a lot of work to declare a new event args class and a new delegate).
Also, the event handler is a tight coupling between view and viewmodel, while you would typically prefer a loose coupling, but if you are aware of that fact and of the consequences, then why not...
Another technique (for example for navigation, dialogs etc) is to declare an interface with the methods you need (for example IDialogService with AskConfirmation and ShowMessage methods). Then have a class implement that interface (that can be the MainWindow/MainPage itself) and pass it to the ViewModel (for example in the View's constructor right after InitializeComponent was called). In the VM, call these methods when needed. This has the advantage of being quite easy to test (simply mock the IDialogService and check that the methods are called).
I typically move between Messenger and IDialogService depending on various factors. I tend to favor the interface based approach lately though, because it is a little easier to test (but the Messenger is quite testable too so YMMV).
Cheers,
Laurent

In a "pure" MVVM solution, the only thing that should connect the View to the ViewModel is Bindings. There is nothing stopping you from casting your DataContext to your ViewModel type and hooking an event in the view, but it kind of defeats the purpose of using the MVVM approach. As an alternative, try to rethink of why you think you need to raise an event to the view:
Need to display a popup? Some variety of bound list of "popup notifications" can be used, with a proper template, to create popups on the view as the viewmodel "inserts" notification objects into the bound collection.
Need to force a drop down open, or some similar UI action? Bind the appropriate property on the UI to a view model property, set the mode to two-way, and set as appropriate on the view model.
etc, etc.

You are right that sometimes the ViewModel needs to communicate with the View. One way to do this is that the ViewModel raises a CLR event which the View listens to. This can be done in the code-behind of the View.
MVVM is not about eliminating the code-behind of the Views! It’s about separation of concerns and improving the testability with unit tests.
Another way to enable the communication between the ViewModel and the View is by introducing an interface (IView). More information about this approach can be found on the WPF Application Framework (WAF) project site.

There is indeed a supported technique in MVVMLight for handling sending Messages from your ViewModel to your View. Look inside the GalaSoft.MvvmLight.Messaging namespace. There is a better way to send dialod messages then the below sample, however this is just a quick example.
Example
ViewModel
public MainPageViewModel()
{
Messenger.Default.Send("Payment");
}
View
public MainPage()
{
Messenger.Default.Register<string>(this, DialogRequested);
}
private DialogRequested(string message)
{
MessageBox.Show(message);
}

Related

ViewModel Event Registration and ViewModel Lifetime

I have an architectural problem, and a possible solution for which I would like an opinion.
I'm used to MVVM architecture for WP7 (whenever possible but unfortunately sometimes the sdk seems to go on the opposite direction).
WP7 force an ViewFirst approach and I feel confortable with this (except for the part that we can't override the View creation, as in Silverlight, to made constructor injection possible).
I found myself confident by having most of the viewmodel follow the lyfetime of its view. So the viewmodel is created when the view is created (by accessing a ViewModelLocator), the ViewModel is (or should) be referenced only by its view, when the view is destroyed also its ViewModel should be destroyed (its not mandatory but its the way i go except in very rare case for which i create a singleton viewmodel).
My viewmodel could need to register to some singleton service events (phoneservice or singleton class i created). I mean, it could need to register to an event of a class which lifetime is not decided by the viewmodel itself.
These events keep an hardreferences to my viewmodel and keep my viewmodel alive even when the view is destoryed, not only, my viewmodel will continue to receive and process the events.
The WeakEvent pattern could be a possible solution but it's unpractible to create an eventmanager for every event. The best solution, in my opinion, does not exist and should be a keyword for a weak registration to events.
A solution I found is to have my viewmodel aware of NavigateTo and NavigateFrom so i can register and unregister events from there. I can also add some logic (for example i could unregister only in case of back) putting attention to have specular logic in NavigateTo and NavigateFrom.
Another possible way (I have not tested) could be to make my viewmodel aware of View finalization and perform some cleanup when the view is finalized but I always had the feeling the this approach is not reccomended beacuse of the use of the finalization. Also it's not clear to me how much the performance will be affected.
What do you think about having the viewmodel lifetime be the same as its view (it always simplified my app until now) ?
What do you think about the NavigateTo-NavigateFrom ViewModel aware solution ?
What do you think about the View-Finalization ViewModel aware solution ?
Have you experienced any of these or maybe another type of solution ?
Regards
SkyG
UPDATE
I found that the finalization solution will not do the work beacuse it can happen in late future (or maybe never).
For now it seems to me that the best solution is a pair of virtual method in the viewmodelbase Initialize and Cleanup for event registration deregistration which the view should call.
A Possible moment to call them could be during loaded and unloaded event (when I don't need my viewmodel process the event if I'm in a subsequent view, in this this case the first view/viewmodel are still alive in the backstack but loaded/unloaded are fired if they view is attached/detached to the visual tree).
Any other opinion (even confermative) will be appreciated.
Thank You
What do you think about having the viewmodel lifetime be the same as
its view (it always simplified my app until now) ?
This sounds reasonable to me, as it's directly related to the DataContext of the view.
What do you think about the NavigateTo-NavigateFrom ViewModel aware
solution ?
I don't think it's a good idea. In the MVVM pattern, ViewModels are supposed to know nothing about the view. Navigation is typically related to views, so I don't think it's the best idea.
What do you think about the View-Finalization ViewModel aware solution
?
Without specifically talking about finalization, a clean-up method for view models is IMO the way to go. In the base class for all your ViewModels (I hope you have one), you could put the following method:
public abstract class ViewModelBase
{
....
public virtual void Cleanup();
}
Then, simply call myViewModel.CleanUp(); when your view is closed.
Unregister your events in the concrete implementation of CleanUp:
public override void CleanUp()
{
....Event -= this....EventHandler;
}
I agree that the weak event idea is nice but it would be too cumbersome to implement. It also creates issues of its own - it can make the viewmodel entirely weak-referenced, making it a candidate for garbage collection way before it actually "should" (developer opinion vs garbage collector opinion). I've been bitten by this before as has Ward Bell in this blog post of his.
Based on your requirements and desire to follow a "pure" approach to MVVM (viewmodel doesn't know about the view), it seems like you are struggling with the balance between the "view" and the "model" of the viewmodel. In this case, I'd actually suggest another design pattern: MVPVM (model / view / presenter / viewmodel). Here's an MSDN article on it.
In your case, the presenter would hold on to those singleton events. It would be okay for the presenter to know about the view because the presenter isn't meant to be reused across views. Your viewmodel would then just become a "model of the view", allowing for reuse and eliminating most vm lifetime issues.
I like the MVPVM approach because it always concerned me in MVVM when my viewmodels started to take on too much responsibility (talking to the data access layer, listening to application-wide events as well as handling commands from the view, maintaining its properties for the view, etc). I know this isn't necessarily an answer to your question but it's too long for a comment.

ViewModel-first approach to Silverlight navigation

I am looking for a truly decoupled way of supporting navigation in a Silverlight application using MVVM. I am trying to accomplish more of a "purist" implementation of the pattern where the UI is completely separated from the ViewModels so that the application can actually run entirely without a UI. To do this, I need to support navigation without UI concerns.
I have several ideas how to accomplish this (with Messaging, etc) but haven't come up with a good way of "mapping" the View to the ViewModel so that the UI can show the appropriate View when the ViewModel is "displayed". I recall coming across an article some time ago that described a solution to this very problem but can't seem to locate it online anymore.
Does anyone know how to find this article or have any experience solving this problem?
So here's my somewhat long-winded description what we ended up doing:
First, we decided to use the built-in Page Navigation framework. We had multiple reasons but since it is built-in and is also the navigation framework du jour in Windows 8, we opted to try this approach.
I should also mention that we use MVVM Light and MEF in our applications. (This comes into play below.)
To make this work, we created an application Shell (UserControl) that contains the Frame control. The Shell's DataContext is set to an instance of the ShellViewModel which exposes a single CurrentPage property (of type String). We then bind the Frame's Source property to CurrentPage. This approach is similar to Rachel's app-level ViewModel.
The ShellViewModel registers with the Messenger to receive CurrentPageChanged messages. When the message is received, the CurrentPage property is updated, the PropertyChanged event raised and the UI updated. The message originates from the NavigationService (which implements INavigationService and is injected/imported using MEF).
The NavigationService exposes a NavigateTo method which accepts the string name of the ViewModel representing the destination. This name matches the contract name applied to the ViewModel when exported (using MEF) and used to lookup the instance using our ViewModelLocator.
In the NavigateTo method, we use the ViewModelLocator to retrieve the ViewModel instance, call Deactivate on the current ViewModel (if one), call Activate on the new ViewModel then send the CurrentPageChanged message with the name of the new view as a parameter. Activate/Deactivate are helper methods on the ViewModels that allow us to perform any necessary tasks when the ViewModel is navigated to or from.
This appears to be working well and gives us a very MVVM-ish implementation with all navigation isolated from our ViewModels via the INavigationService and messaging.
The only down-side right now is that while we are using string constants in code to represent the ViewModel names, we are still hard-coding the strings in the Views to set the DataContext. I will be looking into a way to set the DataContext automatically as part of the navigation 'tooling'.
I should mention that this approach was parsed together from a number of sources, including (but not limited to) Rachel and the following links:
http://blogs.microsoft.co.il/blogs/eladkatz/archive/2011/01/25/adapting-silverlight-navigation-to-mvvm.aspx
http://blog.galasoft.ch/archive/2011/01/06/navigation-in-a-wp7-application-with-mvvm-light.aspx
http://www.geoffhudik.com/tech/2010/10/10/another-wp7-navigation-approach-with-mvvm.html
Usually I have a ViewModel for the entire app, and it contains the CurrentPage and all navigation event handling.
On the View side, I use a ContentControl with it's Content bound to CurrentPage, and use a DataTemplateSelector to determine which View to display for which ViewModel
There's an example here if you're interested, although it uses DataTemplates instead of a DataTemplateSelector.

MVVM: does change notification muddy the separation between model and viewmodel?

Let's say I have a model which exposes a collection of objects which I will display and change in a GUI.
So we have Model exposing a collection of ModelItem.
The View binds to a ViewModel which exposes an ObservableCollection of ViewModelItem. ViewModelItem is the Viewmodel of ModelItem
The View contains a ListBox and a DataTemplate. the DataTemplate is for items of type ViewModelItem. The View DataContext points at an instance of ViewModel. The ListBox binds to the ObservableCollection.
I control all the code.
So far so simple. Question:
Is it acceptable to expose the collection on the Model as an ObservableCollection? Further, is it acceptable to implement INotifyPropertyChanged on Model and ModelItem?
My concern is I'm muddying the separation between model and viewmodel, but then common sense says, here's a mechanism for notifying changes to elements in my model, lets use it...
Just wanted to get some perspective from others.
Thanks
Short answer:
YES. Use your notification interfaces on your model when you need to notify of changes. Do not worry about muddying your code with this. Be pragmatic.
Long answer:
My philosophy goes like this: When implementing MVVM, bind directly to model objects when there is nothing extra to do. When you need something new (new behavior, properties the view will utilize, etc) then you wrap the model objects in ViewModel objects. A ViewModel that does nothing but delegate data from the model is nothing but extra code. The moment you need to do something to that data past what the model object gives you, you introduce the layer.
So, to extend my thoughts further on that, (and to answer your question more directly), there needs to be a way for the model to tell the ViewModel when something changes. Often, model data is immutable so it doesn't need this notification mechanism, so it isn't necessary. BUT, it is also often the case that the model DOES change. When that happens, the model has two options: use a custom notification method (events, delegates, etc) or use INotifyPropertyChanged.
If you look at the namespace for INotifyPropertyChanged, it is in System.ComponentModel -- not the view -- so I prefer to use it in the model. It is a well-known interface and you can use it to bind directly to your model from your view. No need to implement anything different.
Taking this philosophy one step further, ObservableCollection is in System.Collections.ObjectModel -- also not view-specific -- and it implements System.Collections.Specialized.INotifyCollectionChanged which also is not view-specific. In other words, ObservableCollection was designed to be a collection that notifies its observers of changes. If you have a model that needs to do that, then ObservableCollection is your tool. It just happens to be convenient (not by accident, though) that WPF and Silverlight use these interfaces for data binding.
I guess this is a long-winded way of saying: "YES. Use your notification interfaces on your model when you need to notify of changes. Do not worry about muddying your code with this. Be pragmatic."
It is definitely acceptable to do both. I would even say it's required to do both. Your common sense abilities work just fine. :)
I would only add that if you don't need all the MVVM functionality for your ModelItems, then you can cut some corners by exposing an ObservableCollection<ModelItem> instead of an ObservableCollection<ViewModelItem>, and modifying your DataTemplate to suit. This will save you quite a bit of "preparation" code, so weigh the pros and cons.
It's certainly acceptable to use change notification in the data model if the data model needs change notification. It's also questionable to use change notification in the data model just because the UI needs change notification.
Generally, I design the data model as if there were no UI, and use the view model as an abstraction layer that hides the data model's implementation details from the UI. On the other hand, in a dynamic application it can be the case that the need for change notification is pervasive enough that it just makes more sense to put it in the data model.
No. It's horrible. Your model should not know how it is used. Giving it this knowledge defeats the object of MVVM.
The model should never know it is being used by WPF, winforms, a dos console, as a service or as a lib. If you tell it this, you are going wrong.
It should also be framework independent, not minding if it's part of MVVM, MVC or MXXX!

Choosing between bound ViewModel properties or messaging to communicate between ViewModel and View using the MVVM Light Toolkit

I'm using MVVM Light toolkit (which I love). I currently have messaging in place for some interaction originating from the ViewModel and intended for consumption by the View. Typically these types of messages indicate the View should do something like hide itself, show a confirmation message that data was saved, etc.
This works. In the constructor for the View, I register with the Messenger:
Messenger.Default.Register<NotificationMessage<PaperNotification>>(this, n => HandlePaperNotification(n));
When I'm using the Messenger to communicate cross-cutting concerns between ViewModels (like identity), I can see that when the ViewModel is cleaned up in the ViewModelLocator, the base class for ViewModels (ViewModelBase) unregisters any subscribed messages. I don't have to do anything, as MVVM Light Toolkit handles that for me. However, when I use them in the Views, I have to expressly unregister them at Closing time, like so:
Messenger.Default.Unregister(this);
I suppose I could implement a base class for Views to inherit from.
However, it strikes me that perhaps this is a code smell to be using the Messenger in the View... it works, but it might not be the best way. I'm wondering if I should instead create a property on the ViewModel and bind whatever part of the View's elements to it. In the example of hiding a form, a property could be a boolean called "Show". As I think about it, I can see that in many cases this will result in having to write a ValueConverter. One way seems less testable. The other way seems to require much more code and perhaps the introduction of excess ValueConverters, which could become a code smell in themselves.
So (after all that build up) my question is this:
Is it preferable to use messages within the View or is it better to add properties (and potentially ValueConverters) to allow the ViewModel to drive it in a more bindable fashion?
In MVVM. ViewModel comunicates with View through DataBinding and Commands. If you need some other functionality, you need to implement it using this means.
Messaging is supposed to be only for ViewModels. Views are supposed to be "stupid" visualisers of your data in ViewModel.
The Messaging logic in MVVM Light is there for communication between ViewModels. I've never run into any communication between View and ViewModel that I couldn't solve with binding and/or commands. Sometimes I need Value Converters and sometimes I need code in the code-behind, but I've never had to make the ViewModel directly push data to the View.
This is an interesting discussion and I found this thread when I was wondering about view model to view communication. Interestingly, MVVMLight's creator seems to find it perfectly acceptable to send messages from a view model to a view. Another example of differing opinions about what is a good MVVM design.

Need advice on implementing UI in WPF

I need some advice on implementing UIs in WPF.
So far, I've been using Code-Behinds, which is extremely easy to get-started, but hell when maintaining/changing/testing.
I've looked at MVP (and its WPF variant - MVVM), but having some trouble getting started.
Assuming I have a UI to build, here's what I think I should do:
1.
Create a "Main UI" Mediator class which specifies ALL high-level operations (LoadSettings(), SetVisibility() ) and events (not triggered by the user, e.g, model data changed) that my UI supports.
2.
Create the "Model" classes to represent the data
3.
Create "ViewModel" classes for my model classes.
4.
For complex behaviours (e.g, a sequence of operations need to be done before the UI can/should update, such as modifying items in a collection), do not rely on ViewModels to update the UI. Instead, do it manually through the Main UI Mediator class.
5.
For simple behaviours (e.g, toggling the visibility/enabled states/etc), use WPF binding to bind the ViewModels' properties directly to the UI.
In this case, the Main UI Mediator class would maintain both the ViewModel and Model objects, and delegate user interactions (to the Model) and UI update requests (to the ViewModel/View) appropriately. The Mediator class also provides a centralised interface which specifies the functionalities of the UI, while acting as a Change Manager (described in GOF's Observer Pattern) to handle complex UI behaviour/reduce redundant UI updates.
Am I on the right track? Should I tweak my approach? Change it completely? At the moment, I lack the experience/knowledge to implement huge/complex UIs, so I don't really know whether I'm on the right track.
Thanks
This is a bit long, sorry about that!
So far, I've been using Code-Behinds, which is extremely easy to get-started, but hell when maintaining/changing/testing.
Yep :) Anytime you have to name a control and write "someControl dot blah" in your code-behind, that's a code smell. It's sometimes unavoidable, but try to limit it as much as possible. Your UI is a projection of the model - ViewModels and ValueConverters are a way to deal with the impedance mismatch between the two domains.
A few problems with your approach:
Create a "Main UI" Mediator class which specifies ALL high-level operations
Instead of doing this, your Window class acts as the "Controller"; the important thing is, use Commanding to define your top-level actions. This way, you can have UserControls decoupled from the Window class, because the UserControl will just call Commands.Open.Execute(null, this), and the Window can handle it, and the UserControl will never explicitly have a dependency on the Window.
Create "ViewModel" classes for my model classes.
In MVVM, the VM part is to help you out - if you can get away with binding directly to the model (i.e. the data doesn't change or you don't mind implementing INotifyPropertyChanged in your models), then doing this (even if you have to use a few IValueConverter classes) is okay. ViewModels are mostly used when the view is so different from the model representation that it'd be ugly to hack up your model, or to "tack on" extra properties that only make sense in this particular view.
while acting as a Change Manager...
Remember that WPF does this for you, via Dependency Properties and INotifyPropertyChanged; don't reinvent the wheel; if you write an OnDataUpdate() function, this is a sign you're not using data binding properly.
e.g, a sequence of operations need to be done before the UI can/should update, such as modifying items in a collection
This is where Commanding is great - your CanExecute function can apply arbitrarily complex logic to decide whether a certain operation can be done, and if you bind it to UI elements like Menus or Buttons, they will automatically disable/enable as needed.
It hasn't been mentioned, but do all of your UI design in XAML.
There is nothing worse than seeing WPF UI's being created via code-behind.

Resources