February 18, 2014

Closing a Dialog Window in WPF using MVVM

Alot of ideas are mentioned on this website:
http://stackoverflow.com/questions/4376475/wpf-mvvm-how-to-close-a-window

Simplest way is to simply define the close button as normal using the click event
<Button Content="OK" IsDefault="True" Click="okButton_Click" />
Here is the code behind:
private void okButton_Click(object sender, RoutedEventArgs e)
{
 this.Close();
}
This does not affect the ViewModel in any way, the ViewModel knows nothing about the close functionality. and there is nothing wrong with code behind if it does not affect the ViewModel.
However I wanted to be able to initiate the Close from the ViewModel. To do this I defined a property that takes a simple Action delegate
public Action CloseAction { get; set; }
In the constructor I give it a default value
this.CloseAction = () => 
    { Debug.WriteLine("ActivePhotoBackupViewModel - Close Action Undefined"); )};
Now I can use a command to perform the CloseAction
#region Done Command
private RelayCommand doneCommand;

public RelayCommand DoneCommand
{
 get
 {
  return this.doneCommand ?? 
    (this.doneCommand = new RelayCommand(() => 
     {
      DoSomeOtherStuffHere();
      this.CloseAction();
     }
    ));
 }
}
#endregion Done Command
When creating the view model the close action is defined:
...
ActivePhotoBackupViewModel vm = new ActivePhotoBackupViewModel(srcDir, destDir, photoBackupOptions);
PhotoBackupDlg photoBackupDlg = new PhotoBackupDlg();
vm.CloseAction = new Action(() => photoBackupDlg.Close());
...
Could have a used an interface here on a class to perform the same work but then the interface would have had one method so it is simpler just to use a delegate instead ('Action' is a system defined delegate). Also there were no future extra requirements envisaged on this interface (otherwise the interface route would have been worth it). This simple solution does not impede any unit testing of the ViewModel either.

No comments: