Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove event handlers when I'm finished with a View and ViewModel, but not the Model

Tags:

In my application, I am often creating new Views and ViewModels, but persisting the same Models. For example, I might show a simple view of a list of items in my main window, and have another window with further details of any particular item. The detail window can be opened and closed at any time, or multiple windows can be opened simultaneously for different items on the list.

Therefore, there can be more than one ViewModel for a given model object, and they need to be updated with changes from other places. (I'm using INotifyPropertyChanged on my models.) I want to get rid of ViewModels when I am done with them, i.e., as the detail window is closed.

public DetailViewModel(MyDetailModel detailModel)
{
    // Retain the Detail Model
    this.model = detailModel;

    // Handle changes to the Model not coming from this ViewModel
    this.model.PropertyChanged += model_PropertyChanged;  // Potential leak?
}

It is my understanding that the event handler will cause the Model to retain a reference to the ViewModel, and keep it from getting garbage collected.

1) Is this correct? How can I tell if these references are still present?

2) How should I determine the ViewModel is no longer needed and unsubscribe from the events?

like image 759
mbmcavoy Avatar asked Sep 14 '11 22:09

mbmcavoy


People also ask

Does the event handler affect ViewModel references?

It is my understanding that the event handler will cause the Model to retain a reference to the ViewModel, and keep it from getting garbage collected. 1) Is this correct? How can I tell if these references are still present?

What are the options for event handling?

A further option that you can now use easily is the use of anonymous event handlers rather than needing to define private methods to handle the events.

Can there be more than one ViewModel for a given model?

Therefore, there can be more than one ViewModel for a given model object, and they need to be updated with changes from other places. (I'm using INotifyPropertyChanged on my models.)


1 Answers

At first I thought this would be the way to go:

public class DetailViewModel : IDisposable
{
    public DetailViewModel(MyDetailModel detailModel)
    {
        // Retain the Detail Model
        this.model = detailModel;

        // Handle changes to the Model not coming from this ViewModel
        this.model.PropertyChanged += model_PropertyChanged;  // Potential leak?
    }

    public void Dispose()
    {
        this.model.PropertyChanged -= model_PropertyChanged;
    }
}

But then I found this beautiful nugget. So, there are at least two possible solutions: (a) sample implementing IDisposable, and (b) arguments against IDisposable. I'll leave the debate to you. ;)

You may also consider the WeakEvent Pattern among others ...

like image 177
IAbstract Avatar answered Sep 27 '22 18:09

IAbstract