父视图和子视图模型之间通过notifychanged或命令属性进行通信?

sth*_*ird 5 c# wpf mvvm

在我的WPF应用程序中,我遵循MMV模式.我有一个嵌套子视图的主视图.我有一个主VM来保存子VM的实例.在某些时候,当VM VM的某些属性发生变化时,需要通知主VM.

我在网上搜索了很多.首选方法似乎是使用现有框架(MVVMlight/Prism)和/或某种信使服务.每当在任何板/常见问题上询问有关VM交互的问题时,您可以确定至少有一个答案建议使用此方法.虽然我可以很好地看到它在大型应用程序中的优势(或者如果您正在寻找"通用"解决方案),但对于小型应用程序来说,它有时似乎是一个很大的开销.

对我而言,最明显的方法,特别是在小型应用中,将是

  • 订阅子VM的NotifyPropertyChanged.

要么

  • 让主VM将(Relay)命令传递给子VM,以便子VM可以在某个属性发生变化时执行命令(甚至可以将更改后的值作为命令参数传递),这样主VM就知道了这个变化并且可以处理它.

我想知道这两种方法是否存在"错误",因为我看不到它们违反了MVVM规则?也许我错过了什么?

当您无法利用在应用程序中使用基于信使的方法的优势时,可以使用这些方法之一吗?

adm*_*tDK 5

我们为此使用一种简单的方法。创建此子视图模型时,只需将 Action 或 Func 传递给构造函数即可。然后在需要更新父视图模型时调用该操作。

例子

public class ParentViewModel
{
    public ParentViewModel()
    {
        childViewModel = new ChildViewModel(MyAction);
    }

    private void MyAction()
    {
        //i was called by childview model, now do something
    }

    ChildViewModel childViewModel;
}

public class ChildViewModel
{
    private readonly Action action;

    public ChildViewModel(Action action)
    {
        this.action = action;
    }

    private int myVar;

    public int MyProperty
    {
        get { return myVar; }
        set
        {
            myVar = value;
            if (something)
            {
                //call the parent viewmodel
                action.Invoke();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_* M. 2

第一种方法的问题是主虚拟机必须了解子虚拟机的属性,因此您需要将这两者紧密地联系在一起。在使用某种消息传递系统时,您只能将数据传递给“父对象”,而无法传递有关其子对象内部的信息。

第二种方法的问题是可测试性 - 如果您正在为虚拟机编写测试,则必须模拟这些(中继)命令才能使测试正常工作(或者在调用它的方法内进行一些空检查,brrr。 ..)即使这意味着只是传递什么都不做的愚蠢的、空的对象。另外,通常使用消息传递组件会更好,因为它在所有应用程序中都是统一的 - 您不必担心如何在虚拟机之间进行通信,因为您在任何地方都以相同的方式进行通信:)。

作为旁注 - 如果您的应用程序很小(只有主 - 子虚拟机),您可能可以采用您提到的任何方法。然而,即使在小型应用程序中,我也关心模式/实践,因为实现它们非常简单。例如,实现消息传递组件(也许是自定义?)所付出的努力并不比实现其他任何东西所付出的努力大:)。希望这有帮助:)