可观察的接收者

ObservableRecipient 类型是可观察对象的基类,也充当邮件的收件人。 此类是对 ObservableObject 的扩展,并且还内置支持使用 IMessenger 类型。

平台 API:ObservableRecipient、、ObservableObjectIMessengerWeakReferenceMessengerIRecipient<TMessage>PropertyChangedMessage<T>

工作原理

ObservableRecipient 类型旨在用作同时使用 IMessenger 功能的视图模型的基类,因为它对此提供了内置支持。 具体而言:

  • 它既有一个无参数构造函数,也有一个接受 IMessenger 实例的构造函数,用于依赖注入。 它还公开 Messenger 可用于在 viewmodel 中发送和接收消息的属性。 如果使用无参数构造函数,则 WeakReferenceMessenger.Default 实例将分配给 Messenger 该属性。
  • 它公开了一个 IsActive 属性,用于激活/停用该视图模型。 在此上下文中,“激活”是指将给定的 ViewModel 标记为正在使用,例如,它会开始侦听已注册的消息、执行其他设置操作等。有两个相关方法:OnActivatedOnDeactivated,会在该属性的值发生变化时被调用。 默认情况下, OnDeactivated 会自动从所有已注册的消息中注销当前实例。 为了获得最佳结果并避免内存泄漏,建议用于 OnActivated 注册消息,并用于 OnDeactivated 执行清理操作。 这种模式允许视图模型多次启用和禁用,同时确保它在每次停用时都能被安全回收,而不会有内存泄漏的风险。 默认情况下, OnActivated 将自动注册通过 IRecipient<TMessage> 接口定义的所有消息处理程序。
  • 它公开一个Broadcast<T>(T, T, string)方法,该方法通过PropertyChangedMessage<T>属性提供的IMessenger实例发送Messenger消息。 这可用于轻松广播 ViewModel 的属性更改,而无需手动获取一个 Messenger 实例来使用。 此方法被各种 SetProperty 方法的重载版本使用,这些重载版本带有额外的 bool broadcast 属性,用于指示是否还要发送消息。

下面是一个在处于活动状态时接收 LoggedInUserRequestMessage 消息的 ViewModel 示例:

public class MyViewModel : ObservableRecipient, IRecipient<LoggedInUserRequestMessage>
{
    public void Receive(LoggedInUserRequestMessage message)
    {
        // Handle the message here
    }
}

在上面的示例中,OnActivated 会自动将该实例注册为 LoggedInUserRequestMessage 消息的接收者,并使用该方法作为调用时要执行的操作。 使用 IRecipient<TMessage> 接口并非强制要求,也可以手动完成注册(甚至只用一个内联 lambda 表达式即可):

public class MyViewModel : ObservableRecipient
{
    protected override void OnActivated()
    {
        // Using a method group...
        Messenger.Register<MyViewModel, LoggedInUserRequestMessage>(this, (r, m) => r.Receive(m));

        // ...or a lambda expression
        Messenger.Register<MyViewModel, LoggedInUserRequestMessage>(this, (r, m) =>
        {
            // Handle the message here
        });
    }

    private void Receive(LoggedInUserRequestMessage message)
    {
        // Handle the message here
    }
}

示例

  • 查看 示例应用 (适用于多个 UI 框架),以查看 MVVM 工具包的操作。
  • 还可以在 单元测试中找到更多示例。