C# 跨视图模型传递数据

C# 跨视图模型传递数据,c#,wpf,mvvm,architecture,C#,Wpf,Mvvm,Architecture,我就是搞不懂。所以我会尽我所能描述我的问题 我正在使用MVVM模式构建应用程序。我使用viewmodelAAAViewModel的用户控件AAAViewModel来填充数据类CDATA类。我还有主窗口MainView和它的viewmodelMainViewModel。接下来,我有一个窗口DialogView和DialogViewModel 因此现在MainViewModel(具有自己的用户控件)创建了对话框viewmodel(具有另一个用户控件实例)。如何在这两个用户控件之间传输CDATA类中的

我就是搞不懂。所以我会尽我所能描述我的问题

我正在使用MVVM模式构建应用程序。我使用viewmodel
AAAViewModel
的用户控件
AAAViewModel
来填充数据类
CDATA类
。我还有主窗口
MainView
和它的viewmodel
MainViewModel
。接下来,我有一个窗口
DialogView
DialogViewModel

因此现在
MainViewModel
(具有自己的用户控件)创建了
对话框viewmodel
(具有另一个用户控件实例)。如何在这两个用户控件之间传输
CDATA类中的数据?我试图在
AAAViewModel
中创建属性,该属性将保存
MainViewModel
DialogViewModel
的实例,以便我可以向其传递数据,但由于无法将其作为依赖项属性,我被卡住了

我的目标是使用户控件可以在不同的视图中使用,这些视图可以在参考底图
CDataClass
中具有不同的数据

只是想澄清一下。。。我将用户控件用作
,不知道如何在不同视图中的同一用户控件的两个不同实例之间共享数据。任何关于某种模式或方法的观点都将不胜感激


谢谢您的帮助。

我认为将应用程序体系结构图表化为视图之间的关系并不理想;我认为更好的方法是将其视为viewmodels之间的一组关系,根据需要将视图挂在树上。当你这样想的时候,“数据是如何传递的”变得简单多了。视图只是viewmodel和用户之间的管道。你不会把房子设计成一套窗户和电话,然后再试图从中找出建筑平面图。你从房子的用途和人们将如何居住开始

所以这很简单:

某些ViewModel具有
AAViewModel
属性。这些视图模型上可能有各种简单或复杂的视图;如果视图想让用户编辑viewmodel的
AAViewModel
内容,那么它包括一个适当绑定到viewmodel的
AAViewModel
AAView
。您的
MainViewModel
DialogViewModel
都是大型复杂的交互式视图,希望有人能够编辑其虚拟机的
AAViewModel
内容

如果
MainViewModel
DialogViewModel
的父对象,或者创建了一个
DialogViewModel
的临时实例以放入一个模式对话框,那么
MainViewModel
将显示该对话框,并查看
dialogVM.AAVM.CData.IsDirty
以决定如何处理它。或者,在显示对话框之前,它可能会给dialogVM.AAVM
一个新的
CDataClass
实例(可能是它自己实例的克隆),如果
ShowModel()
返回
true
,则它会使用
dialogVM.AAVM.CData

关键是,一旦viewmodels驱动了一切,它们之间的通信就变得相对简单了。亲子关系很简单:父母给孩子东西,看孩子带回来什么。一个viewmodel可以订阅另一个viewmodel的
PropertyChanged
事件;父视图模型可以监视其子视图模型;当孩子身上发生某些事情时,父母可以决定是否更新兄弟姐妹。一般来说,孩子们不应该知道任何关于他们父母的事情;这使得在不同的上下文中重用子视图模型变得更加容易。由家长决定如何处理这些信息

AAViewModel只知道有人递给他一份CDATA类的副本;他相应地更新了他的公共财产。然后其他人(可能是
AAView
,但他不知道)通过设置他的属性给他一些更改;他相应地更新了他的
CDataClass
实例。过了一会儿,他不知道,一个或另一个viewmodel来查看
CDATA类

视图和视图模型之间的通信是通过绑定进行的

更新 事实证明,您正在视图中创建视图模型,因此您不知道父对象如何访问它们。现在您知道了为什么这样创建子视图模型不是一个好主意

以下是如何在我上面介绍的以viewmodel为中心的设计中实现子视图/视图模型:

首先,放弃在视图中创建子viewmodels所做的任何操作

其次,为子viewmodel类型创建一个
DataTemplate
。这应该放在一个资源字典中,该字典被合并到App.xaml中的资源中,但是它非常简单,如果你懒散地将它粘贴到使用它的两个不同视图的
resources
,它不会杀死你

我不知道您的名称空间声明是什么样子的。我将假设视图位于名为
xmlns:view=“…”
的内容中,而视图模型位于名为
xmlns:vm=“…”
的内容中

现在我们可以在
对话框视图中显示
AAAVM

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <ContentControl 
        Content="{Binding AAAVM}" 
        Grid.Row="0"
        />

    <StackPanel Orientation="Vertical" Grid.Row="1">
        <!-- Other stuff -->
    </StackPanel>
</Grid>
请注意,下一个是view codebehind,而不是viewmodel

DialogView.xaml.cs

public static bool? ShowDialog(DialogViewModel dvm)
{
    var vw = new DialogView() { DataContext = dvm };

    return vw.ShowDialog();
}
public static bool? ShowDialog(CDataClass cdc)
{
    var dlg = new DialogView();

    dlg.ViewModel.AAAVVM.CDC = cdc;

    return dlg.ShowDialog();
}
现在,您可以让对话框继续创建自己的viewmodel;在这种情况下,您可以将其作为公共财产,如下所示:

public DialogViewModel ViewModel => (DialogViewModel)DataContext;
还有一个ShowDialog方法,如下所示:

public DialogViewModel ViewModel => (DialogViewModel)DataContext;
DialogView.xaml.cs

public static bool? ShowDialog(DialogViewModel dvm)
{
    var vw = new DialogView() { DataContext = dvm };

    return vw.ShowDialog();
}
public static bool? ShowDialog(CDataClass cdc)
{
    var dlg = new DialogView();

    dlg.ViewModel.AAAVVM.CDC = cdc;

    return dlg.ShowDialog();
}
然后父母可以像这样与它互动:

MainViewModel.cs

public CDataClass CDC { /* you know the drill */ }

public void ShowDialog()
{
    var dvm = new DialogViewModel();

    //  Maybe this isn't what you want; I don't know what CDataClass does. 
    //  But I'm assuming it has a copy constructor. 
    dvm.AAAVM.CDC = new CDataClass(this.CDC);

    if (DialogView.ShowDialog(dvm).GetValueOrDefault())
    {
        CDC = dvm.CDC;
    }
}
public void ShowDialog()
{
    var cdcClone = new CDataClass(this.CDC);

    if (DialogView.ShowDialog(cdcClone).GetValueOrDefault())
    {
        CDC = cdcClone;
    }
}
干净整洁

如果该对话框不是模态对话框,请将对话框viewmodel设置为
MainViewModel
的私有成员,并让
MainViewModel
订阅对话框viewmodel上的事件,以了解该对话框正在执行的操作。每当用户更新对话框的
CDataClass
副本时,对话框都会引发
DataC