Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Show/Hide Windows the MVVM way

0.00/5 (No votes)
17 Jan 2015 1  
Solution to the problem on how to databind Windows visibility to ViewModels

Introduction

Some idea to handle Window and Dialog the MVVM way.

Background

Recently. In my take over the world app, I started to write Window and Dialog (aka Modal Window) ViewModel. I wanted to be able to handle the Window through data binding. I came up with this solution.

Using the code

In a MVVM it is customary to handle most, if not all, app state in your view model. Leaving the UserControl to be empty shell for loading XAML UI definition. As I started to add dialog & window to my app I hit a limitation of the MVVM tool I am familiar with.

I was trying to write

myDialogViewModel.Show = true; // must show window, somehow...

I came up with this utility class hosting Window visibility as AttachedProperties

public class Dialog
{
 public static bool GetShowDialog(Window obj) { return (bool)obj.GetValue(ShowDialogProperty); }

 public static void SetShowDialog(Window obj, bool value) { obj.SetValue(ShowDialogProperty, value); }

 public static readonly DependencyProperty ShowDialogProperty = ...;

 public static bool GetShowWindow(Window obj) { return (bool)obj.GetValue(ShowWindowProperty); }

 public static void SetShowWindow(Window obj, bool value) { obj.SetValue(ShowWindowProperty, value); }

 public static readonly DependencyProperty ShowWindowProperty = ...;
}

I can then use it in XAML as follow:

<MyDialog
 xmlns:gx="clr-namespace:MyApp"
 Title="My Dialog"
 gx:Dialog.ShowDialog="{Binding Show}"
 >
....
</MyDialog>

And voila! Full MVVM dialog and Windows.

Full Source Code

Here is the complete implementation of the Dialog class.

public class Dialog
{
 public static bool GetShowDialog(Window obj) { return (bool)obj.GetValue(ShowDialogProperty); }

 public static void SetShowDialog(Window obj, bool value) { obj.SetValue(ShowDialogProperty, value); }

 public static readonly DependencyProperty ShowDialogProperty = DependencyProperty.RegisterAttached("ShowDialog", typeof(bool), typeof(Dialog)
  , new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, e) => OnShowDialogChanged(o, (bool)e.NewValue)));

 private static void OnShowDialogChanged(DependencyObject sender, bool state)
 {
  var w = sender as Window;
  if (w != null)
  {
   EventHandler closed = (o, e) => { SetShowDialog(w, false); };
   if (state)
   {
    w.Closed += closed;
    // WARNING: this is blocking => screw 2-way binding
    // => call in a Dispatcher
    w.Dispatcher.BeginInvoke(new Action(delegate { if (GetShowDialog(w)) w.ShowDialog(); }));
   }
   else
   {
    w.Closed -= closed;
    w.Close();
   }
  }
 }

 public static bool GetShowWindow(Window obj) { return (bool)obj.GetValue(ShowWindowProperty); }

 public static void SetShowWindow(Window obj, bool value) { obj.SetValue(ShowWindowProperty, value); }

 public static readonly DependencyProperty ShowWindowProperty = DependencyProperty.RegisterAttached("ShowWindow", typeof(bool), typeof(Dialog)
  , new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, (o, e) => OnShowWindowChanged(o, (bool)e.NewValue)));

 private static void OnShowWindowChanged(DependencyObject sender, bool state)
 {
  var w = sender as Window;
  if (w != null)
  {
   EventHandler closed = (o, e) => { SetShowWindow(w, false); };
   if (state)
   {
    w.Closed += closed;
    w.Show();
   }
   else
   {
    w.Closed -= closed;
    w.Close();
   }
  }
 }
}

 

Points of Interest

Ever more MVVM goodness! I didn't see many solution for hiding/showing Windows. I hope this will help!

History

Initial release on 18/01/2015

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here