WPF MVVM窗口导航

时间:2012-07-04 10:15:45

标签: wpf mvvm navigation window

我将MVVM模式应用于我的应用程序,该应用程序将具有数十个屏幕(具有相应的ViewModel)。现在我陷入了一个非常简单的问题......谁有责任创建新窗口,实例化viewModel并将其分配给另一个?

我认为在View中甚至在ViewModel中执行此操作是错误的。我看到许多回复建议使用外部框架,这对我来说不是一个选择。

您怎么看?

Windows的官方推荐是什么?

2 个答案:

答案 0 :(得分:0)

这就是我的所作所为:

  • 以mainviewmodel为应用程序根目录的主窗口
  • 需要时使用viewmodel登录视图
  • viewmodel所有子/模块的第一种方法
  • 对话框驱动的对话框服务视图模型
  • 为Windows驱动的windowservice视图模型

mainviewmodel通过MEF组成模块。

答案 1 :(得分:0)

我们试试一个例子:用户点击一个按钮,会出现一个确认对话框,其中显示是/否。 通常,您会在按钮的事件处理程序中引发通知:

private void Button_Click(object sender, MouseRoutedEventArgs e)
{
    var result = MessageBox.Show("Confirm?", MessageBoxButton.YesNo);
    if (result == true)
        //something
    else
        //something else
}

现在,由于我们有MVVM,因此必须将业务逻辑(此处为if/else)移入ViewModel。但 UI 必须保留在UI控件上! 假设这是ViewModel:

public class VM
{
    public void DoSomething()
    {
        //raise the confirmation interaction
    }
}

ViewModel不能拥有UI ...但可以拥有用户所需交互的摘要。

这可能是互动的界面:

public interface IConfirmationInteraction
{
    bool? RaiseConfirmationRequest(string message);
}

所以ViewModel可以有这样的属性:

public IConfirmationInteraction ConfirmInteraction { get; }

VM未实例化它,VM接受其他人传递的接口实例。例如,在构造函数中:

public VM(IConfirmationInteraction confirmInteraction)
{
    if (confirmInteraction == null)
        throw new ArgumentNullException(nameof(confirmInteration));
    ConfirmInteraction = confirmInteraction;
}

所以它的方法可以变成:

public void DoSomething()
{
    var result = ConfirmInteraction.RaiseConfirmationRequest("Confirm?");
    if (result == true)
        //do something
    else
        //do something else
}

用户界面?您可以创建使用UI元素的具体交互:

public class UIConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return MessageBox.Show(message, MessageBoxButton.YesNo);
    }
}

你明白了吗?我们已经保存了模式:ViewModel与逻辑一起工作,汇集了不同的抽象,但对实现,消息框,按钮等一无所知。 您可以将这些交互实现为UI交互,例如在拥有VM的UI Control的构造函数中:

public class MyControl : USerControl
{
    public MyControl()
    {
        DataContext = new VM(new UIConfirmationInteraction());
    }
}

但您也可以将它们实现为自动结果,例如,当您想要运行测试列表时,尝试默认答案“是”或默认答案为“否”:

public class YesConfirmationInteraction : IConfirmationInteraction
{
    public bool? RaiseConfirmationRequest(string message)
    {
        return true;
    }
}

这称为“依赖注入”。在谷歌上试试,你可以找到几十个教程。在这种情况下,我通过构造函数构建依赖注入

这是一种可靠的方法,您可以通过ViewModel手动构建UI控件之间的所有桥梁,但保留模式。