【问题标题】:WPF MVVM Window navigationWPF MVVM 窗口导航
【发布时间】:2012-07-04 10:15:45
【问题描述】:

我正在将 MVVM 模式应用于我的应用程序,该应用程序将有几十个屏幕(带有各自的 ViewModel)。现在我陷入了一个非常简单的问题……谁负责创建新窗口、实例化 viewModel 并将一个分配给另一个?

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

你怎么看?

Windows 的官方推荐是什么?

【问题讨论】:

  • 关于 MVVM 和导航的问题很多,看右边栏...
  • 没错,每个答案都是关于使用某些第三方框架或使用具有全局 ViewModel 的单个窗口。我的问题是如何在不使用第三方框架或直接在 viewModel 代码中进行的情况下在不同的 Windows 之间切换。
  • Unity 怎么样?这是一个选择吗? (第三方,但微软免费)
  • 我猜官方的 Windows 建议是使用Prism,但这是一个外部框架(虽然它是免费的,由微软开发)
  • 第三方软件的具体问题是什么?微软是否被视为第三方?这会使决策变得非常困难(那么 mscore 也是第三方吗?)

标签: wpf mvvm navigation window


【解决方案1】:

这就是我的工作:

  • 1 个以 mainviewmodel 作为应用程序根的主窗口
  • 在需要时使用视图模型登录视图
  • 所有子/模块的视图模型优先方法
  • 为对话驱动的对话服务视图模型
  • windowservice 为 windows 驱动的视图模型

主视图模型通过 MEF 组合模块。

【讨论】:

    【解决方案2】:

    让我们尝试一个示例:用户单击一个按钮,然后显示一个带有是/否的确认对话框。 通常你会在按钮的事件处理程序中引发通知:

    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 控件的构造函数中:

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 2023-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-04
      • 2016-07-29
      相关资源
      最近更新 更多