gpt4 book ai didi

c# - 无需框架即可相互通信的 ViewModel

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

简介

我有一个在运行时导入实验室仪器数据的应用程序。此数据被导入,然后显示在 ListView 中在最终用户根据他或她的测试要求设置的时间间隔内。当感兴趣的值出现在此 ListView 中时他们观看,然后他们按下开始按钮,应用程序开始对该数据和后续数据执行计算,直到按下停止按钮。因此,屏幕左侧是一个 View ,用于显示导入的数据,右侧是另一个 View ,用于查看计算和显示的值和统计数据。

当前代码

显示导入数据的 ListView 的 View 是 ImportProcessView.xaml,它设置其 DataContextImportProcessViewModel.cs .我刚刚介绍的 VM 有一个属性 ObservableCollection<IrData>我刚才也描述过的 ListView 绑定(bind)到。现在到了有趣的部分......

ImportProcessView有一个 ContentControl动态设置其内容的 UserControl 表示特定于最终用户选择的阶段类型的控件和字段。

<StackPanel Background="White" Margin="5">
<ContentControl Content="{Binding CurrentPhaseView}"/>
</StackPanel>

一共有三个PhaseViews ,每个都有自己的用户控件,每个都设置为 DataContextImportProcessViewModel .结果,我得到了一些严重的 VM 膨胀,达到 2000 行。荒谬的。我知道。膨胀的原因是因为 ImporProcessViewModel通过三个 PhaseView 中的每一个的属性维护状态,不仅如此,还包含执行计算的方法,其数据存储和显示在这些“PhaseView”中。

我正在努力实现的目标

显然在 ImportProcessViewModel 之前变得更加笨拙,我需要将其分解,以便每个 PhaseView 都有自己的 ViewModel,而且每个 ViewModel 为了 IrData 的 ObservableCollection 强加的依赖关系而保持与 ImportProcessViewModel 的关系。 .

研发

我已经研究了 ViewModel 之间的相互通信,但是大多数 results涉及使用特定 MVVM 框架编写的应用程序。我没有使用框架,此时在项目中重构它以开始使用框架为时已晚。

不过,我确实找到了这个 article并且'hbarck'提供的答案建议一些简单的组合来实现我想要的结果,但由于我没有太多使用DataTemplates的经验,我不明白他/她建议公开“the UserControl 的 ViewModel 作为主 ViewModel 的属性,并将 ContentControl 绑定(bind)到该属性,然后通过 DataTemplate 实例化 View (即 UserControl)”

具体来说,我不明白“将 ContentControl 绑定(bind)到此属性,然后将通过 DataTemplate 实例化 View ”是什么意思

有人可以通过代码示例阐明在此示例的上下文中通过 DataTemplate 实例化 View 的含义吗?

此外,这是一个好方法吗(如“hbarck”所建议的那样)?

如您所见,我已经将 ContentControl 的 Content 属性设置为要实例化的 Phase View。我只是不知道涉及 DataTemplate 会是什么样子。

最佳答案

I don't understand what is meant when he/she suggests exposing "the UserControl's ViewModel as a property on the main ViewModel, and bind a ContentControl to this property, which would then instantiate the View (i.e. the UserControl) through a DataTemplate"

DataTemplate 允许您指定 View (例如用户控件)和 View 模型之间的关系。

<DataTemplate DataType="{x:Type myApp:MyViewModel}">
<myApp:MyUserControl />
</DataTemplate>

只要 ContentPresenter 的内容属性设置为 MyViewModel 的实例,它就会显示 MyUserControl。 View 模型将用作用户控件 DataContext。通常,DataTemplate 会添加到您的应用程序资源中。

该答案的作者所说的是,您可以拥有一个 viewModel,该 viewModel 具有另一个 viewModel 类型的属性,该类型绑定(bind)到 ContentPresenterContent 属性.

<ContentPresenter Content="{Binding ParentViewModel.ChildViewModelProperty}"/>

如果您有一个 DataTemplate 指定您的 ChildViewModel 和您的用户控件之间的关系,WPF 将自动将用户控件加载到您的 View 中。

This answer我提供给另一个问题可能也会为您提供一些帮助。

I need to break it up so that each PhaseView has its own ViewModel, but also such that each ViewModel maintains a relationship back to the ImportProcessViewModel.

这将允许您将 viewModel 分解为更小、更易于管理的 viewModel,它们会自行管理。这会给您留下 View 模型之间的通信问题。

如果您按照建议嵌套 viewModel,那么您的子 viewModel 可以公开父 viewModel 可以绑定(bind)到的事件,以便在发生变化时收到通知。像这样:

public class ParentViewModel // Derive from some viewModel base that implements INPC
{
public ParentViewModel()
{
childViewModel = new ChildViewModel();
childViewModel.SomeEvent += someEventHandler;
// Don't forget to un-subscribe from the event at some point...
}

private void SomeEventHandler(object sender, MyArgs args)
{
// Update your calculations from here...
}
}

这很简单,不需要任何额外的框架。有些人可能会反对这种方法,但它是一种有效的解决方案。缺点是 viewModel 必须了解彼此的存在才能订阅事件,因此最终会紧密耦合。不过,您可以使用标准的面向对象设计原则来解决这个问题(即从接口(interface)派生子 viewModel,以便父级只知道接口(interface)而不是实现)。

如果您真的想要松散耦合的通信,那么您需要使用某种事件聚合或消息总线系统。这类似于上面的方法,除了有一个对象位于 View 模型之间并充当中介,这样 View 模型就不必知道彼此的存在。我的answer here提供了更多信息。

有可用的预先存在的解决方案,但这将涉及采用额外的框架。我建议使用 Josh Smiths MVVM foundation因为它非常简单,无论如何您只需要使用一个类。

关于c# - 无需框架即可相互通信的 ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16403743/

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