从反馈ICommand

时间:2017-01-03 12:50:47

标签: wpf mvvm mvvm-light

我有一个ICommand实现,它是独立的。它修改了实体的信息。同一实体绑定到View,作为视图ViewModel的属性。

我想要实现的是,在执行命令后,要使用新信息更新实体(以及因此ViewModel,因此 - View)。我理解它的方式,ICommand - s是单向的。他们修改基础数据,但不应该给出直接结果。

所以我通过使用MVVMLight框架在执行结束时从Command中发送Message来实现这一点。当接收到消息时,公开实体的视图模型也订阅相同的消息并自行更新(更新的信息作为消息的属性传递)。

额外的好处是其他View Models也可以订阅并响应同一事件。什么'气味'但是,关于它,这个实现的主干是events。从我所读过的内容来看,事件的整个概念并不适合MVVM模式。或者可以通过这种方式进行跨VM通信?

示例:

域名模型

  • 用户
    • First Name
    • Last Name
    • Full Name { get { return First Name + Last Name } }

查看模型

  • 用户视图模型 - 环绕User Domain Model,但不存储其实例
    • string First Name
    • string Last Name
    • string Full Name(注意:我们对它的计算方法一无所知)
    • ICommand Change First Name
    • 方法MapFromDomainModel(UserDomainModel)。视图模型收到UserDomainChanged消息时调用。

命令

  • Change First Name : ICommand
    • 更改First Name
    • 中的User Domain Model
    • 发送UserDomainChanged(UserDomainModel)条消息

请参阅,在此示例中,视图模型不知道Full Name的计算方式,并且不知道在First Name发生更改时,不知道Full Name {1}}也应该改变。这就是Command直接在域模型上工作并触发消息的原因。

此外,我可能在窗口中有其他视图,其中视图模型绑定到相同的用户域模型。通过订阅相同的消息,他们可以独立更新自己。

这是一个好方法吗?还有更好的吗?

1 个答案:

答案 0 :(得分:2)

  

我理解它的方式,ICommand-s是单向的。他们修改基础数据,但不应该给出直接结果。

你是对的。 ICommand接口的Execute方法的返回类型为void,这意味着它不会向命令的调用者返回任何类型的值或结果。

  

或者可以通过这种方式进行跨VM通信吗?

是。使用事件聚合器或信使在两个对象之间进行通信和使用普通事件之间的巨大差异是耦合。当您订阅普通事件时,您会在发布者和事件订阅者之间创建紧密耦合。订阅者需要对发布者的强引用,以便能够订阅该事件,并且发布者需要通过事件处理者委托对订阅者的引用才能发布该事件。这导致组件之间的紧密耦合,这反过来趋向于导致较少的可维护应用。

通过在发布者和订阅者之间引入事件聚合器,您可以消除这种紧密耦合。订阅者观察事件聚合器而不是发布者,并且发布者仅知道事件聚合器而不知道订户。如果您想要广泛的图片,请参阅以下博文:https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

  

这是一个好方法吗?还有更好的吗?

是。使用事件聚合器/信使以松散耦合的方式在组件之间进行通信通常是一种好方法。另一种选择是使用共享服务。这只是一个以分离方式为多个组件提供功能的类。它应该实现一个接口,您通常将其注册为IoC容器中的单例:https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf

请注意,在此特定示例中,您可能还将视图模型的FirstName属性绑定到视图中的目标属性,并在您希望视图刷新而不是调用命令时引发FullName属性的PropertyChanged事件但我猜你有理由调用一个命令然后使用事件聚合器或信使向外界发布消息是完全没问题的。