在WPF MVVM中通知ViewModels UserControl事件时的正确方法吗?

时间:2015-10-29 17:28:24

标签: c# wpf mvvm

在我的WPF视图中,我将数据加载到用户控件中,如下所示:

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

然后在ViewModel中:

private ItemEditViewModel _itemEditVm;
public ItemEditViewModel ItemEditVm
{
    get
    {
        return _itemEditVm;
    }
    set
    {
        _itemEditVm = value;
        OnPropertyChanged("ItemEditVm");
    }
}

我有一系列DataTemplates来说明哪个View属于哪个ViewModel。然后在我的业务逻辑中,我可以为UserControl启动一个新的ViewModel,然后将其分配给属性,并且所有工作都按预期工作。

但是,要解决此应用程序中的下一个任务,我需要能够通知父ViewModel UserControl内发生的事件。我在我的孩子ViewModel和父母的监听器上做了一个简单的事件:

public event EventHandler ItemEditViewModelChanged();

因此,当我创建ViewModel时,我只需添加一个监听器:

ItemEditViewModel vm = new ItemEditViewModel(itemId);
vm.ItemEditViewModelChanged += vm_ItemEditViewModelChanged;

并在vm_ItemEditViewModelChanged()中执行需要完成的操作。

然而,我本能地对此感到不舒服。虽然它没有违反任何MVVM原则直接(事情仍然是可测试的,View和ViewModel仍然是分开的),但它似乎不是一种非常灵活的做事方式,它确实在ViewModel类之间创建了不合需要的逻辑链接

有更好的方法吗?我创建和控制UserControls到ContentControls的方法是一种创建子控件的糟糕方法吗?或者我不担心什么?

2 个答案:

答案 0 :(得分:1)

我不确定这对你有用,只是我的想法。

如果您有一个MainViewModel来保存您上面所有其他ViewModels,那么您可以公开Properties/Methods来调用MainViewModel并让MainViewModel做出决定到另一个ViewModel

答案 1 :(得分:1)

我个人更喜欢使用依赖注入来实现这样的事情。通常会有多个通知需要进行,因此首先声明一个接口:

public interface ICustomEventHandler
{
    void Event1();
    void Event2();
    // .. etc
}

然后在子vm中使用依赖注入来注入需要观察它的任何对象:

public class ChildVM
{
    [Inject] public ICustomEventHandler Watcher {get; set;}

    // .. etc ..
}

首先,这使得模拟变得非常容易,因此您的单元测试已经涵盖,但更重要的是,您已经正式化了此模块与其余代码之间的依赖关系,并且还保留了关于如何最好地实现它的选项。 (一个简单的解决方案是父进程直接实现该接口并在创建时将自身注入到子进程中,在另一种情况下,您可能需要使用具有单独作用域或多个客户端的中间类。)