我将 MVVM 模式应用于我的应用程序,该应用程序将有几十个屏幕(使用各自的 ViewModel)。现在我陷入了一个非常简单的问题......谁有责任创建新窗口,实例化 viewModel 并将一个分配给另一个?
我认为在 View 甚至 ViewModel 中这样做是错误的。我看到许多建议使用外部框架的回复,这对我来说不是一个选择。
你怎么看?
Windows 的官方推荐是什么?
我将 MVVM 模式应用于我的应用程序,该应用程序将有几十个屏幕(使用各自的 ViewModel)。现在我陷入了一个非常简单的问题......谁有责任创建新窗口,实例化 viewModel 并将一个分配给另一个?
我认为在 View 甚至 ViewModel 中这样做是错误的。我看到许多建议使用外部框架的回复,这对我来说不是一个选择。
你怎么看?
Windows 的官方推荐是什么?
这就是我所做的:
mainviewmodel 通过 MEF 组成模块。
让我们尝试一个示例:用户单击一个按钮,然后显示一个带有是/否的确认对话框。通常你会在按钮的事件处理程序中引发通知:
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 交互,例如在拥有以下内容的 UI 控件VM
:
public class MyControl : USerControl
{
public MyControl()
{
DataContext = new VM(new UIConfirmationInteraction());
}
}
但是您也可以将它们实现为自动结果,例如,当您想要运行测试列表尝试默认答案“是”或默认答案“否”时:
public class YesConfirmationInteraction : IConfirmationInteraction
{
public bool? RaiseConfirmationRequest(string message)
{
return true;
}
}
这称为“依赖注入”。在谷歌上试试,你可以找到几十个教程。在这种情况下,我通过构造函数构建了一个依赖注入。
这是一种可靠的方式,您可以通过 ViewModel 手动构建 UI 控件之间的所有桥梁,但保留模式。