【问题标题】:Dealing with message loops in MVVM Light处理 MVVM Light 中的消息循环
【发布时间】:2014-06-27 17:49:17
【问题描述】:

我的应用中有多个对象,它们都发送和接收相同的消息。例如:当用户在网格上拖放列时,当用户使用网格设置对话框以及当用户加载不同的报表时,可以更改网格的列顺序。因此,网格既可以发送“列顺序已更改”消息,也可以接收该消息。

有没有办法阻止 Grid 取回自己的消息?因此,当用户拖动一列时,网格会向所有感兴趣的侦听器发送“列顺序已更改”消息,但我不希望网格随后收到对其订阅的回调。我可以使用谓词并在消息中嵌入一些发件人信息,但我想知道 Mvvm Light 是否可以自己处理这种情况。

【问题讨论】:

    标签: c# mvvm-light


    【解决方案1】:

    查看 IMessenger 注册方法的重载:

    /// <summary>
    /// Registers a recipient for a type of message TMessage.
    ///             The action parameter will be executed when a corresponding
    ///             message is sent. See the receiveDerivedMessagesToo parameter
    ///             for details on how messages deriving from TMessage (or, if TMessage is an interface,
    ///             messages implementing TMessage) can be received too.
    /// 
    /// <para>
    /// Registering a recipient does not create a hard reference to it,
    ///             so if this recipient is deleted, no memory leak is caused.
    /// </para>
    /// 
    /// </summary>
    /// <typeparam name="TMessage">The type of message that the recipient registers
    ///             for.</typeparam><param name="recipient">The recipient that will receive
    ///             the messages.</param><param name="token">A token for a messaging
    ///             channel. If a recipient registers using a token, and a sender sends
    ///             a message using the same token, then this message will be delivered to
    ///             the recipient. Other recipients who did not use a token when
    ///             registering (or who used a different token) will not get the message.
    ///             Similarly, messages sent without any token, or with a different
    ///             token, will not be delivered to that recipient.</param><param name="receiveDerivedMessagesToo">If true, message types deriving from
    ///             TMessage will also be transmitted to the recipient. For example, if a SendOrderMessage
    ///             and an ExecuteOrderMessage derive from OrderMessage, registering for OrderMessage
    ///             and setting receiveDerivedMessagesToo to true will send SendOrderMessage
    ///             and ExecuteOrderMessage to the recipient that registered.
    /// 
    /// <para>
    /// Also, if TMessage is an interface, message types implementing TMessage will also be
    ///             transmitted to the recipient. For example, if a SendOrderMessage
    ///             and an ExecuteOrderMessage implement IOrderMessage, registering for IOrderMessage
    ///             and setting receiveDerivedMessagesToo to true will send SendOrderMessage
    ///             and ExecuteOrderMessage to the recipient that registered.
    /// </para>
    /// </param><param name="action">The action that will be executed when a message
    ///             of type TMessage is sent.</param>
    void Register<TMessage>(object recipient, object token, bool receiveDerivedMessagesToo, Action<TMessage> action);
    

    注意:

    消息通道的令牌。如果收件人使用令牌注册,并且发件人使用相同的令牌发送消息,则该消息将传递给收件人。其他在注册时未使用令牌(或使用不同令牌)的收件人将不会收到该消息。同样,没有任何令牌或使用不同令牌发送的消息将不会传递给该收件人。

    您可以做的是让该消息的其他寄存器使用令牌注册,然后当网格发送消息时使用该令牌发送。网格的注册不应包含令牌。

    【讨论】:

    • 是的,我看到了。但是为此使用令牌的问题是,每个发布者都需要自己的令牌,每个订阅者都需要订阅自己的令牌以外的每个令牌。您添加到系统中的发布者越多,这就会变得非常混乱且难以维护。就我而言,我有 3 个可以发送和接收的对象,第四个可以接收。我可以扩展 Mvvm Light,因此当您发送消息时,您可以传递一个对象,如果它与注册时使用的接收对象相同,则不会传递消息。
    • @MattS 也许您的网格需要发布不同类型的消息,它不订阅的类型。必须有区别,因为消息需要以不同的方式处理。
    • 每个发布者都会对同一消息有自己的风格,他们都需要订阅不同的风格。
    • @MattS 如何拦截网格列移动并取消它,但仍然发送消息。然后让处理程序进行移动,就像在其他任何地方一样。
    • 如何将 GetHashCode() 作为 ID 添加到消息中。如果是您的身份证,请忽略它。或者在消息中为您的对象添加一个实例(例如 object Sender { get; set; },如果是您忽略它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多