C# 在MVVM中跨多个ViewModel传播/冒泡事件

C# 在MVVM中跨多个ViewModel传播/冒泡事件,c#,wpf,xaml,mvvm,C#,Wpf,Xaml,Mvvm,我有一个MainWindow.xaml,其中DataContext设置为MainWindowViewModel.cs。在用户单击按钮并向窗口添加MyUserControl.xaml之前,此窗口中没有任何内容。MyUserControl.xaml将MyUserControlViewModel.cs设置为DataContext 我想在MyUserControlViewModel.cs中触发一个事件,该事件被MainWindowViewModel.cs 到目前为止,我有这个。在myMyUserCont

我有一个
MainWindow.xaml
,其中
DataContext
设置为
MainWindowViewModel.cs
。在用户单击按钮并向窗口添加
MyUserControl.xaml
之前,此窗口中没有任何内容。
MyUserControl.xaml
MyUserControlViewModel.cs
设置为
DataContext


我想在
MyUserControlViewModel.cs
中触发一个事件,该事件被
MainWindowViewModel.cs


到目前为止,我有这个。在my
MyUserControlViewModel.cs中

public event EventHandler<LoadingEventArgs> LoadingEvent;
(...)

public void MyFunction() {
    LoadingEvent(this, EventLibrary.LoadingEvent(2));
}
private MyUserControlViewModel _myUserControlViewModel;
public MyUserControlViewModel _MyUserControlViewModel {
    get { return _myUserControlViewModel; }
    private set { _myUserControlViewModel = value; OnPropertyChangedEvent("MyUserControlViewModel"); }
}

public MainWindowViewModel() {
    // Can't attach event here
}

public void AddEventToUserControl() {
    _MyUserControlViewModel = new MyUserControlViewModel();
    _MyUserControlViewModel.LoadingEvent += MyUserControlViewModel_LoadingEvent;
}

private void MyUserControlViewModel_LoadingEvent(object sender, LoadingEventArgs e) {
    MessageBox.Show("I got here!");
}
由于
MyUserControlViewModel.cs
中的
LoadingEvent
null
,因此消息
“我到了这里”
从未显示出来 我之所以只在
MainWindowViewModel()
函数之外附加
MyUserControlViewModel\u LoadingEvent
,是因为
MyUserControl.xaml
不是在windows加载时添加的,而是在用户单击按钮后添加的。
我认为这里的问题在于,添加事件的时间与创建
MyUserControlViewModel.cs


我需要知道当通过代码动态创建ViewModels时,如何通过ViewModels触发冒泡事件。


更新-添加更多信息
鉴于我的上述情况可能过于简单,缺乏重要的细节,我将描述我的确切情况。

我有三种观点——祖父、父亲和儿子。对于每一个,我都有一个ViewModel类。在我的父亲中,我在XAML中声明了儿子,因为它是同时创建的,所以当我在父亲视图模型中有
SonViewModel=new SonViewModel()
时,它指向正确的位置,我可以在
SonViewModel
中访问我需要的所有内容。因此,
SONWiewModel
中触发的任何事件都会被
FatherViewModel
监听。
这里最重要的两个事实是父和子都是同时创建的,子是在XAML中创建的,如下所示:

<View:SonView DataContext="{Binding SonViewModel, Mode=OneWay}" />
因为我在创建
GrandfatherView
并通过代码添加它之后创建了
FatherView
,并且没有特定的绑定,所以当我在
GrandfatherViewModel
类中创建
FatherViewModel
对象时,它没有指向我在应用程序中看到的父视图的实际视图模型。
我不确定如何在代码中创建绑定,因此我可以确保属性和绑定是相同的,因此我在我的
祖父视图模型中的ViewModel对象实际上是我在应用程序中看到的对象,而不是一个全新的对象。


所以,有什么建议吗?

问题的完整解决方案(使用Mvvm Light):

GrandFatherView.xaml

<Window x:Class="FunWithDynamicallyCreatedViewModels.GrandFatherView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Name="MainGrid" />
</Window>
<UserControl x:Class="FunWithDynamicallyCreatedViewModels.FatherView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:FunWithDynamicallyCreatedViewModels">

    <local:SonView DataContext="{Binding SonViewModel}" />

</UserControl>
FatherView.xaml

<Window x:Class="FunWithDynamicallyCreatedViewModels.GrandFatherView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid Name="MainGrid" />
</Window>
<UserControl x:Class="FunWithDynamicallyCreatedViewModels.FatherView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:FunWithDynamicallyCreatedViewModels">

    <local:SonView DataContext="{Binding SonViewModel}" />

</UserControl>
SonView.xaml

<UserControl x:Class="FunWithDynamicallyCreatedViewModels.SonView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Button Command="{Binding InvokeEventCommand}" 
            Content="Invoke SonViewModel Event" />

</UserControl>

AddEventToUserControl()中是否有输入错误?您的意思是“MyUserControlViewModel”而不是“MainContentViewModel”?是的,这是一个输入错误,感谢您的注意。如果
LoadingEvent
为空,则表示没有人成功订阅该事件。问题中没有提供足够的信息来说明原因。例如,我无法判断您在
AddEventToUserControl
中创建的
MyUserControlViewModel
实例是否实际分配给控件的
DataContext
。旁注:您可能应该查看,这是天赐的。@McGarnagle,实际上,MyUserControlViewModel的实例没有被分配到DataContext。如果我试图更改该对象的属性,什么都不会发生,所以我猜它没有指向正确的位置应该工作吗?它返回一个错误,指出当前上下文中不存在
Set
。我遗漏了什么吗?@josemartins.grupoma您是否在项目中添加了对MvvmLightLibs NuGet包的引用?Set(…)是来自ViewModelBase类的方法,该类是MvvmLight库的一部分。该方法缺失,我的错。如果没有
命令
绑定到
用户控制视图
按钮,如何在
用户控制视图模型
中直接触发
InvokeEventCommand
?您的问题中不清楚触发事件的责任人。它可以是用户(如我的示例中所示),也可以是一些第三方代码,也可以是UserControlViewModel本身。在哪个代码中:UserControlViewModel、WindowViewModel、AnotherViewModel?在任何情况下,这段代码都是由某物或某人触发的:)我不清楚程序的执行流程。你想达到什么目标?也许你可以提供问题的高级描述?如果需要在viewmodels之间传递值,可以使用中介方法作为事件的替代方法(MvvmLight中的IMessenger,Caliburn.Micro中的IEventAggregator)。
<UserControl x:Class="FunWithDynamicallyCreatedViewModels.SonView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Button Command="{Binding InvokeEventCommand}" 
            Content="Invoke SonViewModel Event" />

</UserControl>
public sealed class SonViewModel
{
    public SonViewModel()
    {
        InvokeEventCommand = new RelayCommand(() => Event(this, new EventArgs()));
    }

    public event EventHandler Event;

    public ICommand InvokeEventCommand { get; private set; }
}