gpt4 book ai didi

c# - 从 ViewModel 打开/关闭 View

转载 作者:太空狗 更新时间:2023-10-29 23:23:19 25 4
gpt4 key购买 nike

我有一个 AddClientViewModel,它被 2 个 View (AddClientView 和 SuggestedAddressesView)引用。 AddClientView 是一个表单,其中包含一个地址字段。该表单有一个验证按钮,它使用地理编码验证输入的地址。如果返回多个地址,则打开 SuggestedAddressesView。

这是我目前的做法:

添加客户端 View 模型:

    private void ValidateExecute(object obj)
{
SuggestedAddresses = new ObservableCollection<DBHelper.GeocodeService.GeocodeResult>(GeoCodeTest.SuggestedAddress(FormattedAddress));

....

if (SuggestedAddresses.Count > 0)
{
var window = new SuggestedAddressesView(this);
window.DataContext = this;
window.Show();
}
}

这里是 SuggestedAddressesView 的构造函数,其中 AddClientViewModel 继承自 ViewModelBase

    public SuggestedAddressesView(ViewModelBase viewModel)
{
InitializeComponent();
viewModel.ClosingRequest += (sender, e) => this.Close();
}

我遇到的另一个问题是当我从 AddClientViewModel 调用 OnClosingRequest() 时...AddClientView 和 SuggestedAddressesView 都关闭了。我知道发生这种情况是因为两个 View 都引用相同的 ViewModel。这不是我想要的行为。我希望能够独立关闭任一窗口。

从 ViewModel 打开一个 View 是否是正确的 MVVM 结构,我将如何独立关闭窗口?

最佳答案

一旦您从 VM 引用 UI 元素(在本例中为 View ),您就违反了建议的 MVVM 准则。由此我们可以知道在 VM 中创建 Window 对象是错误的。

所以现在要纠正这个问题:

  • 首先尝试在您的应用程序中保留 1 个 View <-> 1 个虚拟机。它更简洁,允许您非常轻松地切换出具有相同逻辑的 View 实现。将多个 View 添加到同一个虚拟机,即使不是“突破性的”,也只会让它变得笨拙。
  • 因此,现在您获得了带有自己的 VM 的 AddClientViewSuggestedAddressesView。太棒了!

从虚拟机实现 View 打开/关闭:

  • 由于我们无法直接从 VM 访问 View (为了符合标准),我们可以使用诸如使用 Messenger(MVVM Light)、EventAggregator( PRISM) 等当你需要打开/关闭一个 View 并在 View 中进行实际操作时,从虚拟机向 View 发送“消息”。
  • 通过这种方式,VM 只会启动消息,并且可以针对相同的操作进行单元测试,并且不会引用任何 UI 元素。

使用“Messenger”方法处理 View 打开:

  • 根据您的逻辑,AddClientViewModel 必须要求打开 SuggestedAddressesView
  • 因此,当您检测到 SuggestedAddresses.Count > 0 时,您会向 AddClientView 发送一条消息,要求它打开 SuggestedAddressesView
  • AddClientView.xaml.cs 中收到此消息后,您将执行当前在 VM 中执行的操作。创建一个 SuggestedAddressesView 对象并对其调用 .Show()
  • 您要在上述步骤的过程中添加的一个额外步骤是将 SuggestedAddressesViewDataContext 分配为 SuggestedAddressesViewModel

就是这样。现在你所拥有的是,当 AddClientViewModel 想要显示 SuggestedAddressesView 时,它会向它自己的 View 发送一条消息,然后 View 会创建并显示 SuggestedAddressesView。这样 VM 就不会引用任何 View ,并且我们会继续保持 MVVM 标准。

使用“Messenger”方法处理 View 关闭:

  • 关闭View 非常简单。同样,当您需要从 VM 关闭 View 时,您会向它自己的 View 发送一条消息,要求将其关闭。
  • 收到此消息后, View 几乎通过 .Hide()/.Close() 或您想要摆脱它的其他方式自行关闭。

在这种情况下,每个 VM 都会处理它自己的 View 关闭,并且您没有任何相互连接的依赖关系。

您可以使用 this作为指导您处理此方法的“消息”的起点。它有一个附加的下载文件,您可以下载并查看 Messenger 的工作原理。这是与 MVVM Light 一起使用的,如果您不使用它或使用其他东西/您自己的 MVVM 实现,请将其用作指南以帮助您获得所需的东西。

关于c# - 从 ViewModel 打开/关闭 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18435173/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com