MVVMLight:这是使用Messenger的正确方法吗?

时间:2011-07-26 20:26:27

标签: c# wpf mvvm-light

我有一个管理客户和地址的经典商业应用程序。

每个自己的ViewModel都有标签项(Id,Gen​​ericInfo和更多)。

有一个MainViewModel可以处理客户端及其地址的保存和加载命令。

我们从WCF服务检索数据。从每个WCF功能接收/发送的数据汇总在不同的容器中。


在我的MainViewModel中,我创建了一个SaveContainer,然后使用messenger发送它。

    public void Save()
    {
        var container = new SaveContainer();

        MessengerInstance.Send(container);

        //the container is now populated and ready to be sent via WCF

        Console.WriteLine(container.User.Name);
        Console.WriteLine(container.Address.StreetName);
        Console.WriteLine(container.Address2.StreetName);
    }

在我的UserViewModel中注册该容器,然后viewmodel用它拥有的数据(用户)填充它。

    public UserViewModel()
        : base(Messenger.Default)
    {
        User = new User();

        MessengerInstance.Register<SaveContainer>(this, (x) => x.User = User);
    }

在我的AddressViewModel中,我也这样做。

    public AddressViewModel()
        : base(Messenger.Default)
    {
        Address = new Address();
        Address2 = new Address() { StreetName = "Washington Street" };

        MessengerInstance.Register<SaveContainer>(this, x =>
        {
            x.Address = Address;
            x.Address2 = Address2;
        });
    }

当我必须加载数据时,我也会这样做。


发送消息后,我假设每个注册的ViewModel都收到了消息并进行了处理。我错了吗?你觉得这种方式是使用Messenger的正确方法吗?你会改进什么?

2 个答案:

答案 0 :(得分:2)

没有正确的方式来使用信使。但是,您必须考虑该消息由已注册该消息的所有收件人处理,而不仅仅是预期的子集。此外,在使用消息传递时,您无法控制消息处理何时完成,现在,当所有收件人完成处理消息时,您会收到通知。另外 - 根据信使的实现 - 消息可以并行处理。

因此,您的方法(以及使用回调的@cadrell0扩展)的问题在于您不知道所有收件人何时处理了该消息。使用回调,您将获得处理邮件的每个收件人的回调(即n个收件人n回调)。

那么如何检查所有收件人何时完成处理邮件?

  • 您使用计数器来确定有多少收件人回拨 - 这很容易出错,因为您可能会注册另一个邮件收件人,这会弄乱您的系统。
  • 另一种方法是验证保存容器,一旦完成继续处理 - 但这可能会导致竞争条件,因为您可能认为所有收件人都处理了邮件并继续,但是一个后期收件人调用并使您的邮件无效保存容器...不好。

正如我所看到的,消息传递更多地被设计为通知机制,即您通知某些收件人发生了某些事情。如果您知道并且可以确保只有一个收件人,您甚至可以按照您描述的方式使用它,但只要涉及多个收件人,就会导致上述问题。

那么这会让你离开...在你的szenario我倾向于将视图模型设计为“相关”(即主视图模型知道关于用户视图模型和< / strong>地址视图模型 - 或主视图模型知道关于用户视图模型,如果更合适,则知道关于地址视图模型。通常,我也会设计一个包含我必须处理的工作单元的模型(在你的情况下是SaveContainer)。然后,从该模型构造所有视图模型并将其数据写入其中。在正常情况下,这个工作单元是您从数据存储服务获得的,而这又是由数据存储在单个事务中保存的。

但同样,MVVM没有正确的方式!

答案 1 :(得分:0)

如果我需要在收件人回复邮件后做某事我在邮件中加入回调。收件人完成后,它会执行回调。向回调添加参数允许收件人将数据发送给发件人。这也允许收件人执行异步操作。