Closing a WPF window from a view model.

So you’ve embraced using WPF and the MVVM model, and you may have already been impressed with how easy it is to create powerful user interfaces.  But as with most technologies or patterns sometimes it’s not obvious how to accomplish even the simplest tasks.

Case and point, you have a wpf window that represents a view and a command in that view model that is supposed to close that view.  In the MVVM pattern, the viewmodel is unaware of any view (in this case a window) that it is presenting.  It doesn’t have a reference to the window, so it can’t simply call “window.Close()”.

You could put and event in your view model, that the window could suscribe to that event with a handler that closes the window.  It works, but it’s not really consistant with the MVVM pattern. When using WPF and MVVM, the view only ever receives notification that a property has changed.  So to signal the window to close, all it really needs is to know that a property has changed.

Now, it would be nice if there was a property on a window that could be bound to the view model… a property like IsOpen…   Fortunatly with WPF, one can add properties to any view.  Thanks to attached dependancy properties.

On his excellent WPF blog Josh Smith talks about the concept of using attached dependancy properties, to attach behaviors to a control that wouldn’t otherwise behave that way.  Using this same approach, we can create an attached property for a window that can be bound.


    public static class WindowBehaviors
    {
        public static readonly DependencyProperty IsOpenProperty =
                 DependencyProperty.RegisterAttached("IsOpen", typeof(bool), typeof(WindowBehaviors),
                 new PropertyMetadata(IsOpenChanged));

        private static void IsOpenChanged(DependencyObject obj,
                                          DependencyPropertyChangedEventArgs args)
        {
            Window window = Window.GetWindow(obj);

            if (window != nulll && !((bool)args.NewValue))
                window.Close();
        }

        public static bool GetIsOpen(Window target)
        {
            return (bool)target.GetValue(IsOpenProperty);
        }

        public static void SetIsOpen(Window target, bool value)
        {
            target.SetValue(IsOpenProperty, value);
        }
    }

With the dependancy property created, you can now use the bindable IsOpen property on your window:

<Window ...
        xmlns:wb="clr-namespace:WpfApplication" 
        wb:WindowBehaviors.IsOpen="{Binding IsOpen}"
        ... 

and just like that, when the IsOpen property of the view model is set to false, the window will close.

Advertisement
This entry was posted in MVVM, WPF. Bookmark the permalink.

3 Responses to Closing a WPF window from a view model.

  1. Anastacia says:

    I certainly learned about a majority of this, but with that said, I still believed it was helpful. Good blog!

  2. David Klimek says:

    public static readonly DependencyProperty IsOpenProperty =
    DependencyProperty.RegisterAttached(“IsOpen”, typeof(bool?), typeof(WindowBehaviors),
    new PropertyMetadata(IsOpenChanged));

    This should be “typeof(bool?)” instead of “typeof(bool)” to get it work.

    • Dan Graham says:

      Thank-you for your comment, but it’s not actually necessary for the property to be of type(bool?). That said, it may be desirable to use type(bool?) in many cases.

      In my example here, the dependency property is watching specifically for a transition of the bound property from true to false. When using type(bool) for IsOpen, it must be bound to a property that is set to true either when your view model is created, or at some point before the view model tries to close the window. Setting an already false property to false won’t result in a property change event being called. I’m using this exact code in a production application, and in all the places that I’m using this code, it’s bound to a bool property that is initialized to true in the viewmodel. As you mentioned however, you can avoid that problem by using a bool? Instead, which has no value by default, thus setting it to false is still a change to the property and results in the window closing. One could also invert the Boolean logic and call the property “IsClosed” instead; since all bool variables are false by default.

      Using type(bool?) has another good advantage though when using dialog windows in particular. If you use type(bool?) for the dependency property. You can set the window’s DialogResult in the IsOpenChanged method instead of calling Window.Close(). I wouldn’t recommend calling the dependency property “IsOpen” in that case of course, but if you’re using MVVM for dialog windows it has the added benefit of the result being returned by the window’s ShowDialog() method.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s