ViewModel Event Registration and ViewModel Lifetime - silverlight

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.

Related

Should I always implement INotifyPropertyChanged interface in model?

If I have a model which is pretty much a readonly collection and dispayed on a grid, where the user selects a row.
Do I need to have INotifyPropertyChanged always implemented on the model? Is there a performance benefit of implementing vs not?
I would like to know if performance is impacted by UI trying to use something like
var x = Model as INotifyPropertyChanged;
which it wouldn't have used otherwise.
If you are using the model in any data bindings, then yes, you should implement INotifyPropertyChanged even if it is completely immutable. The reason has nothing to do with performance, but to avoid a memory leak.
A Binding will always try to register for change notifications, and if you do not implement INotifyPropertyChanged or expose discrete change events of the form [Property]Changed, it will register through the PropertyDescriptor API. The default, reflection-based PropertyDescriptor implementation uses a global subscription table, and if for some reason the Binding does not unsubscribe cleanly, your view model will be kept alive indefinitely. This is in contrast to the weak event pattern used when bindings subscribe to INotifyPropertyChanged notifications. Bindings at runtime generally clean up after themselves, but the Xaml designer is notorious for leaking under these circumstances, causing your designer process's memory consumption to rise steadily as you work.
If you are just displaying in on a DataGrid and not expecting any UI interaction that'll change the value of the Model then you do not have to implement INPC.
WPF is tied to the INPC mechanism to update the UI from the backing Model. You don't need it if you load it once and won't change again. However, INPC can be pretty handy and you need to implement it if say a business logic that requires you to update something to a different row then you can basically subscribe the other model's PropertyChangedEvent to do something to the other row when a property changed is raised.
There is no performance benefit of implementing it.

MVVM With Silverlight

I have been downloading a lot of example code to help me gain a better understanding of MVVM within silverlight.
One of the things I have noticed is an inconsistency within the sample code I have downloaded. Some for example implement INotifyPropertyChanged on the viewmodels, where others implement it on the Model.
Which is the preferred way of handling property changes, should it be handled at the model level or the viewmodel level?
Handling (Notifying) property changes in the viewmodel would seem more natural if this is to update the item that's being displayed in the view by databinding.
One of the reasons for having a viewmodel in the first place is that it holds the data from the model in such a way that it's easy for the view to bind to it.
So, if the main reason for your INotifyPropertyChange in is to update the item which is bound in the view, you should update it in the viewmodel.
I typically use DependencyProperty instead of INotifyPropertyChanged, but the idea is the same.
Their purpose is to notify the view controls, they are bound to, that they have changed so the view can update. This implies a weak connection between the view and whatever holds the property or object. In MVVM, the view should never have any link to the model because of separation of concerns.
I will often have physically force this by creating a separate project for each of the view, viewmodel, and model. So, the answer to your question is that the INotifyPropertyChanged should be implemented at the viewmodel level because the view should never touch anything from the model level. Having said this, MVVM is just a coding paradigm to make the programmers job easier, so there could be reasons to implement it differently if it means making your job easier and it doesn't having any negative consequences.

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.

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

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);
}

What's the best way to avoid memory leaks in WPF PRISM/MVVM application

I have a WPF application based on PRISM that utilizes the MVVM pattern.
I have noticed that occasionally my view models, views and everything connected to them will hang around long after their intended lifespan.
One leak involved subscribing to CollectionChanged on a collection belonging to an injected service, another involved not calling the Stop method on a DispatcherTimer, and yet another required a collection be cleared of it's items.
I feel using a CompositePresentationEvent is probably preferable to subscribing to CollectionChanged, but in the other scenarios I am leaning towards implementing IDisposable and have the views call the Dispose method on the view models.
But then something needs to tell the view when to call Dispose on the view model, which gets even less attractive when the complexity of the views increase, and they start including child views.
What do you think is the best approach to handling view models, to ensure they don't leak memory?
Thanks in advance
Ian
I can tell you that I've experienced 100% of the pain you have experienced. We are memory leak brothers, I think.
Unfortunately the only thing I've figured out to do here is something very similar to what you are thinking.
What we've done is create an attached property that a view can apply to itself to bind a handler to the ViewModel:
<UserControl ...
common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>
Then our ViewModel just has a method on it of type Action:
public MyVM : ViewModel
{
public Action CloseAction
{
get { return CloseActionInternal; }
}
private void CloseActionInternal()
{
//TODO: stop timers, cleanup, etc;
}
}
When my close method fires (we have a few ways to do this... it's a TabControl UI with "X" on the tab headers, that kind of thing), I simply check to see if this view has registered itself with the AttachedProperty. If so, I call the method referenced there.
It's a pretty roundabout way of simply checking to see if the DataContext of a View is an IDisposable, but it felt better at the time. The problem with checking the DataContext is you might have sub view models that also need this control. You'd either have to make sure your viewmodels chain forward this dispose call or check all of the views in the graph and see if their datacontexts are IDisposable (ugh).
I sort of feel like there is something missing here. There are a few other frameworks that attempt to mitigate this scenario in other ways. You might take a look at Caliburn. It has a system for handling this where a ViewModel is aware of all sub view models and this enables it to automatically chain things forward. In particular, there is an interface called ISupportCustomShutdown (I think that's what it's called) that helps mitigate this problem.
The best thing I've done, however, is make sure and use good memory leak tools like Redgate Memory Profiler that help you visualize the object graph and find the root object. If you were able to identify that DispatchTimer issue, I imagine you are already doing this.
Edit: I forgot one important thing. There is a potential memory leak caused by one of the event handlers in DelegateCommand. Here's a thread about it on Codeplex that explains it. http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4065
The latest version of the Prism (v2.1) has this fixed. (http://www.microsoft.com/downloads/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en).
My findings so far...
In addition to PRISM, Unity, WPF and MVVM we are also using Entity Framework and the Xceed data grid. Memory profiling was done using dotTrace.
I ended up implementing IDisposable on a base class for my view models with the Dispose(bool) method being declared virtual allowing sub classes the chance to clean up as well.
As each view model in our application gets a child container from Unity we dispose it as well, in our case this ensure that EF's ObjectContext went out of scope. This was our major source of memory leaks.
The view model is disposed within an explicit CloseView(UserControl) method on a base controller class. It looks for an IDisposable on the DataContext of the view and calls Dispose on it.
The Xceed data grid seems to be causing a fair share of the leaks, especially in long running views. Any view that refreshes the data grid's ItemSource by assiging a new collection should call Clear() on the existing collection before assigning the new one.
Be careful with Entity Framework and avoid any long running object contexts. It's very unforgiving when it comes to large collections, even though you have removed the collection if tracking is turned on, it will hold a reference to every item in the collection even though your no longer hanging on to them.
If you don't need to update the entity retrieve it with MergeOption.NoTracking, especially in long lived views that bind to collections.
Avoid views with a long life, don't hold onto them within a region when they are not visibile, this will cause you grief especially if they refresh their data at regular intervals when they are visible.
When using CellContentTemplates on the Xceed Column don't use dynamic resources as the resource will hold a reference to the cell, which in turn keep the entire view alive.
When using CellEditor on the Xceed Column and the resource is stored in an external resource dictionary add x:Shared="False" to the resource containing the CellEditor, once again the resource will hold a reference to the cell, using x:Shared="False" ensures you get a fresh copy each time, with the old one being removed correctly.
Be careful when binding the DelegateCommand to items within the Exceed data grid, if you have a case such as a delete button on the row which binds to a command, be sure to clear the collection containing the ItemsSource before closing the view. If you're refreshing the collection you also need to reinitialize the command as well as the command will hold a reference to each row.

Resources