简体   繁体   中英

WPF & MVVM - Close Window from within Child control

I need to close a modal window from a ViewModel based on a click command that is triggered in a control that is presented within the window.

So, I have MainViewModel, JimViewModel, JimWindow and JimControl. MainViewModel creates a JimWindow and sets its DataContext to JimViewModel. JimWindow contains JimControl, which contains a button. When this button is clicked, I'd like to trigger a command that somehow closes JimWindow.

I've seen a few questions that answer this with respect to closing the Window from the actual Window (By passing the instance of the Window to a Command on the ViewModel), but it doesn't translate to what I want to do.

I'm not using a framework so I have no handy messenger to assist me. Can anyone help? Is it a case of somehow referencing the Name of the parent window from the control?

MainViewModel should not be creating windows, at least not directly. VMs should only create VMs. A window is part of the view world.

If you need your JimVM hosted in a window, then it would be better to have some kind of WindowService abstracted away behind an interface. MainVM then just creates JimVM and gives it to the window service to host in a window

Once you've got the windows bit decoupled into a separate service, then you can do all your crufty window stuff in there. I would have JimVM expose a CloseCommand and a Closed event. You can bind your JimControl button to the CloseCommand , and the windows service can subscribe to the Close event, and tear down the window when it fires.

This keeps the view and VM stuff completely separate. The only thing that knows how to glue the two together is the window manager.

Although idea of ViewModel creating a View sounds a little backwards, you could use messaging, eg TinyMessenger or Messenger that comes with MVVMLight .

You could then register for a message in your View/ViewModel and send it from-anywhere. A really simplistic example using MVVMLight could be:

// custom message
public class CloseMessage : MessageBase
{
    public CloseMessage(object sender)
        :base(sender)
    {}
}

// main view registers for a message
public partial class MainWindow : Window
{
    public MainWindow()
    {
        Messenger.Default.Register<CloseMessage>(this, message =>
        {
            // do teh stuff
        });
    }
    ...
}

// command bound to close button sends the message
private void YourCloseMainViewCommand()
{
    Messenger.Default.Send(new CloseMessage(this));
}

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