1

我是 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();
}

你怎么看待这件事?破解还是好的解决方案?感谢反馈节拍

4

6 回答 6

2

ViewModelMVVM 场景中,不必了解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;
    }
}
于 2012-05-31T16:22:58.357 回答
1

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

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

如果您希望您的 UserControl 能够关闭其父窗口,则向 UserControl 添加一个简单的 Close 事件。现在,在您的 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();
}
于 2012-05-31T16:16:08.450 回答
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;
}
于 2012-06-01T06:33:07.233 回答
0

您的视图模型应该只打开一个DialogService。看这里以获得一个起点。

于 2012-06-01T06:19:49.543 回答
-1

如果你要做 MVVM,你会想要一个 MVVM 框架。我推荐Caliburn.Micro,看看它的窗口管理器

于 2012-05-31T16:33:59.343 回答
-1

这个怎么样?

Window parentWindow = (Window)this.Parent;
parentWindow.Close();
于 2013-11-13T22:25:53.810 回答