简体   繁体   中英

Closing a Window from its content's ViewModel in MVVM WPF?

Creating a Window like so, using my custom UserControl as the content:

Window newCacheForm = new Window
{
    Title = "Add New Cache Tag",
    Content = new NewCacheControl()
};

I want to open the Window as a dialog and get the result:

var result = newCacheForm.ShowDialog();

I have the code in place to bind and set the dialog to true or false, but how do I close the Window from the UserControl ViewModel? If that can't be done, how do I work this in an MVVM friendly way?

In this case I would use an attached behavior, it allows using independent logic on the side of View . I personally did not create it, but took here and little supplemented - added Get() to a dependency property.

Below as a full code of this behavior:

public static class WindowCloseBehaviour
{
    public static bool GetClose(DependencyObject target)
    {
        return (bool)target.GetValue(CloseProperty);
    }

    public static void SetClose(DependencyObject target, bool value)
    {
        target.SetValue(CloseProperty, value);
    }

    public static readonly DependencyProperty CloseProperty = DependencyProperty.RegisterAttached("Close",
                                                                                                  typeof(bool),
                                                                                                  typeof(WindowCloseBehaviour),
                                                                                                  new UIPropertyMetadata(false, OnClose));

    private static void OnClose(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool && ((bool)e.NewValue))
        {
            Window window = GetWindow(sender);

            if (window != null)
                window.Close();
        }
    }

    private static Window GetWindow(DependencyObject sender)
    {
        Window window = null;

        if (sender is Window)
            window = (Window)sender;

        if (window == null)
            window = Window.GetWindow(sender);

        return window;
    }
}

In the Click handler of creating new Window I added this behavior like this:

private void Create_Click(object sender, RoutedEventArgs e)
{
    Window newCacheForm = new Window
    {
        Title = "Add New Cache Tag",
        Content = new TestUserControl(),
        DataContext = new TestModel() // set the DataContext
    };

    var myBinding = new Binding();                // create a Binding
    myBinding.Path = new PropertyPath("IsClose"); // with property IsClose from DataContext
    newCacheForm.SetBinding(WindowCloseBehaviour.CloseProperty, myBinding); // for attached behavior 

    var result = newCacheForm.ShowDialog();

    if (result == false) 
    {
        MessageBox.Show("Close Window!");
    }
}

And in the Close handler of UserControl write this:

private void Close_Click(object sender, RoutedEventArgs e)
{
    TestModel testModel = this.DataContext as TestModel;
    testModel.IsClose = true;
}

Naturally, instead of Click handlers for the Buttons should be used the commands.

The entire project is available here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM