Disposing a timer inside a ViewModel, upon closing the main window
Asked Answered
P

2

1

Currently in my application, I have a RelayCommand which calls an action which starts a Timer. I have a separate command which the calls the Dispose() method to get rid of/release the timer. This all sits in the ViewModel counterpart of the project.

Using the MVVM pattern, how would I dispose of this Timer upon closing the window, as well as carrying out the regular/default operation of closing the window?

I am also using the MVVM-Light toolkit, if this is of any help.

An example of my current solution is shown below:

ViewModel

private static Timer dispatchTimer;

public MainViewModel()
{
    this.StartTimerCommand = new RelayCommand(this.StartTimerAction);
    this.StopTimerCommand = new RelayCommand(this.StopTimerAction);
}

public RelayCommand StartTimerCommand { get; private set; }
public RelayCommand StopTimerCommand { get; private set; }

private void StartTimerAction()
{
    dispatchTimer = new Timer(new TimerCallback(this.IgnoreThis), null, 0, 15);
}

private void StopTimerAction()
{
    dispatchTimer.Dispose();
}

View (xaml)

....
Height="896"
Width="1109"
DataContext="{Binding Main, Source={StaticResource Locator}}">

    <Grid x:Name="mainGrid"
          Width="Auto"
          Height="Auto">              
          <Button x:Name="startTimerButton"
                  Content="Start Timer"
                  Command="{Binding StartTimerCommand}"/>
           <Button x:Name="stopTimerButton"
                   Content="Stop Timer"
                   Command="{Binding StopTimerCommand}"/>
    </Grid>

</Window>

View (Code-Behind)

public MainWindow()
{
    this.InitializeComponent();

    //Would a 'Closing +=' event be called here?
}
Pemberton answered 18/5, 2015 at 12:27 Comment(0)
D
2

Closing the windows may or may not dispose your viewmodel, depending how you register it. One approach would be bind to the Loaded/Unloaded events from the view and do the work there:

View:

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <i:InvokeCommandAction Command="{Binding PageLoadedCommand}"/>
    </i:EventTrigger>
    <i:EventTrigger EventName="Unloaded">
        <i:InvokeCommandAction Command="{Binding PageUnLoadedCommand}"/>
    </i:EventTrigger>
</i:Interaction.Triggers>

ViewModel:

public RelayCommand PageUnLoadedCommand { get; private set; }
...
 PageUnLoadedCommand = new RelayCommand(() => OnPageUnLoadedCommand());

...

    private void OnPageUnLoadedCommand()
    {
        //Unsubscribe and dispose here
    }
Diastema answered 18/5, 2015 at 13:2 Comment(2)
I already have this xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity", which I am assuming is the same as what you posted. Will give this a go now. Cheers.Pemberton
It's not the same, "i" is just a name I gave it, use a different one if that's already used.Diastema
K
-1

You can add a destructor for your ViewModel like below

~public MainViewModel()
{
   dispatchTimer.Dispose();
}
Kissee answered 18/5, 2015 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.