简体   繁体   English

WPF UserControl MVVM如何关闭对话框

[英]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. 我是MVVM的新手,并且遇到了如何打开对话框并随后在其自己的ViewModel c#文件中关闭对话框的问题。 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: 定义了一个UserControl并使用以下命令打开它:

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

    window.ShowDialog(); 
}

In the ViewModel of the UserControl file implement: 在UserControl文件的ViewModel中实现:

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: 最后在Close方法中:

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 . MVVM场景中的ViewModel不必了解有关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. 许多人使用许多不同的模式从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). 您可以通过在UserControl内部引用this.Parent(只要它是第一个内容元素)来更轻松地访问窗口。

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. 您尝试执行的一种更传统的方法是为Window创建一个新的XAML文件,将您的UserControl实例放置在XAML的Window内。

If you want your UserControl to be able to close its parent window, then add a simple Close event to the UserControl. 如果希望您的UserControl能够关闭其父窗口,则向UserControl添加一个简单的Close事件。 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. 现在,您可以在Window XAML中将事件处理程序添加到close事件,并在UserControl引发事件时让Window调用Close()。

// 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. 然后,如果要添加任何其他选项或样式,可以将其添加到XAML中,例如SizeToContent,WindowStartupLocation,BorderStyle等,以控制对话框的外观。

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 . 您的viewmodel应该只打开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 . 如果要进行MVVM,则需要MVVM框架 I recommend Caliburn.Micro , and have a look at its window manager . 我推荐Caliburn.Micro ,看看它的窗口管理器

How about this one? 这个怎么样?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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