简体   繁体   中英

WPF UserControl MVVM how to close a dialog

I'm new to MVVM and run into the problem how to open a dialog and close afterwards the dialog in its own ViewModel c#-file. Search for possible solution and found nothing suitable. My solution looks as follows, but I'm not sure if this has some drawbacks. Defined a UserControl and open it with:

void ChangeDataPathExecute()
{
    Window window = new Window
    {
        Content = new ChangeDataRootPathUserControl(),
    };

    window.ShowDialog(); 
}

In the ViewModel of the UserControl file implement:

private void DetermineMyWindow()
{
    foreach (Window window in App.Current.Windows)
    {
        ChangeDataRootPathUserControl uc = window.Content as ChangeDataRootPathUserControl;
        if (uc == null)
            continue;

        myWindow = window;
    }

and finally in the Close method:

void OkChangeDataRootPathExecute()
{
    DetermineMyWindow();

    myWindow.Close();
}

What do you think about this? Hack or good solution? Thanks for feedback Beat

The ViewModel in an MVVM scenario shouldn't have to know anything about the View . In your example, it seems to have to know a lot about the view.

Many people use many different patterns to open/close windows from the ViewModel. I prefer events/callbacks:

class ViewModel {
    public event EventHandler ChangeDataRootPath;
}

class View : Window {
    public View() {
        InitializeComponent();

        var vm = new ViewModel();
        vm.ChangeDataRootPath += (s, e) => {
            Window window = new Window {
                Content = new ChangeDataRootPathUserControl {
                    DataContext = vm
                }
            };
            window.ShowDialog(); 
        };
        DataContext = vm;
    }
}

You can access the window more easily by referencing this.Parent from inside the UserControl (as long as it is the first content element).

A more orthodox method for what you're trying to do would be to create a new XAML file for a Window, place an instance of your UserControl inside the Window in the XAML.

If you want your UserControl to be able to close its parent window, then add a simple Close event to the UserControl. Now in your Window XAML you can add an event handler to the close event and have the Window call Close() when the UserControl raises the event.

// UserControl.cs
public event EventHandler Close;

void OkChangeDataRootPathExecute()
{
    if (Close != null)
        Close(this, EventArgs.Empty);
}


// Window.cs
void UserControl_Close(object sender, EventArgs e)
{
    Close();
}

Then if you want to add any extra options or styling you can add it to your XAML, such as SizeToContent, WindowStartupLocation, BorderStyle, etc., to control the look and feel of your dialog.

Then when you want to show your dialog in code, you write it like:

void ChangeDataPathExecute()
{
    var window = new ChangeDataRootPathWindow();

    window.ShowDialog();
}

your viewmodel should just open a DialogService . look here to get a starting point.

In my personal implementations, I don't let my view model to know anything about windows, user controls or any other visual elements. But this needs the definition of a whole framework. There are plenty, just search and use the one that fits you best.

But to a quick solution, if the window you want to close from anywhere is the one that currently has the focus, you can use this method to access it:

public static Window GetCurrentFocusedWindow()
{
    Window window = null;

    Control currentControl = System.Windows.Input.Keyboard.FocusedElement as Control;

    if (currentControl != null)
        window = Window.GetWindow(currentControl);

    return window;
}

If you're going to do MVVM, you'll want an MVVM framework . I recommend Caliburn.Micro , and have a look at its window manager .

How about this one?

Window parentWindow = (Window)this.Parent;
parentWindow.Close();

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