Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ViewModels在没有框架的情况下相互通信_C#_Wpf_Mvvm - Fatal编程技术网

C# ViewModels在没有框架的情况下相互通信

C# ViewModels在没有框架的情况下相互通信,c#,wpf,mvvm,C#,Wpf,Mvvm,导言 我有一个在运行时导入实验室仪器数据的应用程序。该数据被导入,然后以最终用户根据其测试要求设置的间隔显示在列表视图中。当感兴趣的值出现在他们观察的列表视图中时,他们按下开始按钮,应用程序开始对该数据和后续数据执行计算,直到按下停止按钮。因此,屏幕左侧是一个用于显示导入数据的视图,右侧是另一个用于在计算和显示值和统计数据时查看它们的视图 当前代码 显示导入数据的ListView的视图是ImportProcessView.xaml,它将其DataContext设置为ImportProcessVi

导言

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

当前代码

显示导入数据的ListView的视图是ImportProcessView.xaml,它将其
DataContext
设置为
ImportProcessViewModel.cs
。我刚才介绍的VM有一个属性
observecteCollection
,我刚才也描述了ListView绑定到该属性。现在来看有趣的部分

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

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

有三个
PhaseViews
,每个都在自己的用户控件中,每个都将其
DataContext
设置为
ImportProcessViewModel
。因此,我得到一些严重的虚拟机膨胀到2000行左右。荒唐的我知道。膨胀的原因是,
importProcessViewModel
通过三个PhaseView中每个的属性来维护状态,不仅如此,还包含用于执行计算的方法,其数据存储和显示在这些“PhaseView”中

我正在努力实现的目标

显然,在
ImportProcessViewModel
变得更加笨拙之前,我需要将其分解,以便每个PhaseView都有自己的ViewModel,但为了
IrData
的ObservableCollection所施加的依赖性,每个ViewModel都要维护回ImportProcessViewModel的关系

研发

我已经研究了ViewModels之间的通信,但大多数都涉及使用特定MVVM框架编写的应用程序。我没有使用框架,在项目的这一点上,重构它开始使用框架已经太晚了

然而,我确实发现了这一点,而“hbarck”提供的答案表明,要实现我想要的结果,需要一些简单的组合,但由于我对数据模板没有太多经验,我不理解他/她建议公开的意思UserControl的ViewModel作为主ViewModel上的属性,并将ContentControl绑定到此属性,然后该属性将通过DataTemplate实例化视图(即UserControl)

具体来说,我不理解“将ContentControl绑定到此属性,然后通过DataTemplate实例化视图”是什么意思

有人可以通过一个代码示例来澄清在这个示例的上下文中通过DataTemplate实例化视图是什么意思吗

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

正如大家所看到的,我已经将ContentControl的Content属性设置为要实例化的阶段视图。我只是不知道涉及DataTemplate会是什么样子

我不明白他/她建议揭露“真相”是什么意思 UserControl的ViewModel作为主ViewModel上的属性,并绑定 此属性的ContentControl,然后它将实例化 通过数据模板查看(即UserControl)

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

<DataTemplate DataType="{x:Type myApp:MyViewModel}">
    <myApp:MyUserControl />
</DataTemplate>
如果您有一个指定
ChildViewModel
和用户控件之间关系的
DataTemplate
,WPF将自动将用户控件加载到视图中

我提供的另一个问题也可能为您提供一些帮助

我需要将其分解,以便每个PhaseView都有自己的ViewModel, 但也要确保每个ViewModel都保持与 ImportProcessViewModel

这将允许您将viewModels拆分为更小、更易于管理的viewModels,这些viewModels可以自行管理。这将给您带来viewModels之间的通信问题

如果按照建议嵌套viewModels,则子viewModels可能会公开父viewModel可以绑定到的事件,以便在发生更改时收到通知。类似如下:

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...
    }
}
<DataTemplate DataType="{x:Type my:Phase1VM}">
  <my:Phase1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:Phase2VM}">
  <my:Phase2View/>
</DataTemplate>
<DataTemplate DataType="{x:Type my:Phase3VM}">
  <my:Phase3View/>
</DataTemplate>
<ContentControl Content="{Binding CurrentPhaseVM}"/>
这很简单,不需要任何额外的框架。有些人可能会反对这种方法,但它是一种有效的解决方案。缺点是viewModels必须知道彼此的存在,才能订阅事件,因此最终可能会紧密耦合。您可以使用标准的面向对象设计原则不过要绕开这一点(即,从接口派生子视图模型,以便父视图只知道接口而不知道实现)

如果你真的想进行松散耦合的通信,那么你需要使用某种类型的事件聚合或消息总线系统。这与上述方法类似,只是有一个对象位于视图模型之间,充当中介,这样视图模型就不必知道彼此的存在。My提供了更多的信息

有现成的解决方案可供使用,但这需要采用额外的框架。我建议使用,因为它非常简单,而且您只需要使用单个类。

<ContentControl Content="{Binding CurrentPhaseVM}"/>