WPF UserControl MVVM如何关闭对话框

时间:2012-05-31 16:01:35

标签: c# wpf mvvm

我是MVVM的新手,遇到了如何打开对话框并在其自己的ViewModel c#-file中关闭对话框的问题。搜索可能的解决方案,找不到合适的。 我的解决方案如下所示,但我不确定这是否有一些缺点。 定义UserControl并使用以下命令打开它:

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

    window.ShowDialog(); 
}

在UserControl文件的ViewModel中实现:

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

        myWindow = window;
    }

最后在Close方法中:

void OkChangeDataRootPathExecute()
{
    DetermineMyWindow();

    myWindow.Close();
}

您如何看待这个?黑客或好的解决方案? 感谢您的反馈 打

6 个答案:

答案 0 :(得分:2)

MVVM场景中的ViewModel不应该对View有任何了解。在你的例子中,它似乎必须对视图有很多了解。

许多人使用许多不同的模式来打开/关闭ViewModel中的窗口。我更喜欢事件/回调:

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;
    }
}

答案 1 :(得分:1)

您可以通过从UserControl内部引用this.Parent(只要它是第一个内容元素)更轻松地访问窗口。

您正在尝试做的更正统的方法是为Window创建一个新的XAML文件,将一个UserControl实例放在XAML中的Window中。

如果您希望UserControl能够关闭其父窗口,则将一个简单的Close事件添加到UserControl。现在,在您的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();
}

然后,如果你想添加任何额外的选项或样式,你可以将它添加到你的XAML,如SizeToContent,WindowStartupLocation,BorderStyle等,以控制你的对话框的外观。

然后,当您想要在代码中显示对话框时,您可以将其写为:

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

    window.ShowDialog();
}

答案 2 :(得分:0)

您的viewmodel应该只打开 DialogService 。看here得到一个起点。

答案 3 :(得分:0)

在我的个人实现中,我不会让我的视图模型知道有关窗口,用户控件或任何其他可视元素的任何信息。但这需要整个框架的定义。有很多,只需搜索并使用最适合你的那个。

但是对于快速解决方案,如果您要从任何地方关闭的窗口是当前具有焦点的窗口,您可以使用此方法来访问它:

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;
}

答案 4 :(得分:-1)

如果你打算做MVVM,you'll want an MVVM framework。我推荐Caliburn.Micro,并查看其window manager

答案 5 :(得分:-1)

这个怎么样?

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