父子ViewModel之间采用NotifyChanged或Command属性进行通信?

7
在我的WPF应用程序中,我遵循MMV模式。我有一个主视图和嵌套的子视图。我有一个主VM,它持有子VM的实例。在某些情况下,当子VM的某些属性更改时,主VM需要被通知。
我搜索了很多网页。首选的方法似乎是使用现有的框架(MVVMlight/Prism)和/或某种信使服务。每当在任何论坛/常见问题解答上提出与VM交互有关的问题时,你可以确定至少有一个答案建议使用这种方法。虽然我可以非常清楚地看到在大型应用程序中(或者如果您正在寻找“通用”解决方案),它的优点,但对于小型应用程序来说,这有时似乎是过多的开销。
对我来说,在小型应用程序中最明显的方法是:
订阅子VM的NotifyPropertyChanged。

将(Relay)命令传递给子VM,以便子VM可以在某个属性更改时执行该命令(甚至将更改后的值作为命令参数传递),这样主VM就知道更改并可以处理它。
我想知道在一般情况下是否有问题使用这两种方法,因为我没有看到它们违反MVVM规则?也许我漏掉了什么?
当您无法利用基于信使的方法的优势时,使用这些方法是否可以?

1
实际上,如果您正在使用IoC,则使用类似IEventAggregator的东西比您的两个解决方案都要容易得多。如果您正在开发小型应用程序,并且不关心模式/实践等等,那么您可以使用任何您想要的东西。此外,您可以在子VM中定义特殊事件,并将其用于通知父VM有关某些更改的信息。 - tym32167
3个回答

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();
            }
        }
    }
}

1
这种方法似乎类似于将命令传递给子视图模型的方法。我认为命令比动作或函数更符合“mvvm”的风格。但是你的方法当然也可以很好地工作。 - sth_Weird

2
第一种方法的问题在于主VM必须知道子VM的属性,因此你会将这两者紧密地联系在一起。而使用某种消息系统,您只能将数据传递给“父级”,而不提供其子对象的内部信息。
第二种方法的问题是可测试性-如果您正在为您的VM编写测试,那么您必须模拟那些(Relay)Commands,以使您的测试工作正常(即使它意味着仅传递无用的空对象)。此外,通常使用消息组件更好,因为它在整个应用程序中都是统一的-您不必担心如何在VM之间通信,因为您在任何地方都是以相同的方式进行通信:)。
顺便说一句-也许如果您的应用程序很小(只有主-子vm),您可以使用您提到的任何方法。然而,我关心即使在小应用程序中也要实现模式/做法,因为实现它们足够简单。例如,实现(可能是自定义的?)消息组件所需的付出的努力并不比您必须采取其他任何措施大:)希望这有帮助:)

0

查看将子视图模型中所做的更改通信选项,以及它们与其父视图模型之间的关系。对于小型应用程序,您完全可以不使用消息总线、事件聚合器。

  1. 父级订阅由子视图模型发出的INotifyPropertyChanged事件没有任何问题。如果您不需要松散耦合这些组件,则使父级依赖于子级是可以接受的。

  2. 从父级传递命令给子级是不可取的,因为如果父级也需要调用子级上的命令,则很可能会设置一个依赖循环。

  3. 如果您的应用程序真的很小,另一个选择就是只有一个视图模型。一个或多个视图共享数据上下文是可以的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接