Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use disposable view models in WPF?

How do I ensure view models are properly disposed of if they reference unmanaged resources or have event handlers such as handling elapsed on a dispatcher timer. In the first case, a finaliser is an option, although not ideal, but in the latter, it will never be called. How can we tell when there is no longer a view attached to the view model.

like image 458
ForbesLindesay Avatar asked Aug 08 '11 14:08

ForbesLindesay


People also ask

How use MVVM pattern in WPF?

The single most important aspect of WPF that makes MVVM a great pattern to use is the data binding infrastructure. By binding properties of a view to a ViewModel, you get loose coupling between the two and entirely remove the need for writing code in a ViewModel that directly updates a view.

What is MVVM model in WPF?

MVVM (Model-View-ViewModel) MVVM is a way of creating client applications that leverages core features of the WPF platform, allows for simple unit testing of application functionality, and helps developers and designers work together with less technical difficulties.

What is MVVM pattern in C#?

MVVM is an architectural pattern that is represented by three distinct components, the Model, View and ViewModel. In order to understand these three layers, it is necessary to briefly define each, followed by an explanation of how they work together. Model is the layer that drives the business logic.


2 Answers

I accomplished this by doing the following:

  1. Removing the StartupUri property from App.xaml.
  2. Defining my App class as follows:

    public partial class App : Application
    {
        public App()
        {
            IDisposable disposableViewModel = null;
    
            //Create and show window while storing datacontext
            this.Startup += (sender, args) =>
            {
                MainWindow = new MainWindow();
                disposableViewModel = MainWindow.DataContext as IDisposable;
    
                MainWindow.Show();
            };
    
            //Dispose on unhandled exception
            this.DispatcherUnhandledException += (sender, args) => 
            { 
                if (disposableViewModel != null) disposableViewModel.Dispose(); 
            };
    
            //Dispose on exit
            this.Exit += (sender, args) =>
            { 
                if (disposableViewModel != null) disposableViewModel.Dispose(); 
            };
        }
    }
    
like image 111
Jas Laferriere Avatar answered Oct 08 '22 09:10

Jas Laferriere


One possible, although not perfect solution:

Implement IDisposable on the View Model, then use this extension method in the constructor of the view.

    public static void HandleDisposableViewModel(this FrameworkElement Element)
    {
        Action Dispose = () =>
            {
                var DataContext = Element.DataContext as IDisposable;
                if (DataContext != null)
                {
                    DataContext.Dispose();
                }
            };
        Element.Unloaded += (s, ea) => Dispose();
        Element.Dispatcher.ShutdownStarted += (s, ea) => Dispose();
    }
like image 26
ForbesLindesay Avatar answered Oct 08 '22 08:10

ForbesLindesay