首页 > 解决方案 > 使用 ObservableAsPropertyHelper 激活/停用

问题描述

激活/停用与 ObservableAsPropertyHelper 结合的正确用法是什么?给定一个反映长期(热)可观察对象的视图和视图模型,当视图和视图模型被卸载时,订阅需要被释放。然而,建议只读的 ObservableAsPropertyHelper 是在 viewmodel 的构造函数中分配的,不能成为激活/停用生命周期的一部分。处理这种情况的正确方法是什么?

public interface ILongLivedObject
{
    IObservable<bool> Status { get; }
}


public class TestViewModel : ReactiveObject
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status); //how is the subscription disposed?
    }


}

在尝试添加取决于此状态的命令时,这也让我陷入了困境。在我的应用程序中,一个常见的用例是让某些硬件处于某种特定状态(例如 IsOpen),并在其为真时允许命令。在不了解的情况下,这就是我想要做的事情:


public class TestViewModel : ReactiveObject
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;

    public ReactiveCommand<Unit, Unit> DoStuff {get;}

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status); //how is the subscription disposed?
         DoStuff = ReactiveCommand.CreateFromTask(....., this.WhenAnyValue(this, x => x.Status);
    }


}

如果我尝试将 _status 创建移动到 this.WhenActivated 中,则应用程序将崩溃,因为该命令试图在创建状态之前获取它的值。我应该在激活期间(重新)创建命令吗?这似乎是错误的,而且成本很高?

到目前为止,最好有一个带有受保护设置器的常规 Status 属性并在 this.WhenActivated 中进行常规订阅 - 但这是手册告诉避免“只读”属性的内容。

标签: c#disposereactiveui

解决方案


所以在反应式编程中需要注意的一件事是,处理通常意味着“取消订阅”。

您通常不需要取消订阅,因为垃圾收集器会为您处理它,只为您创建ObservableAsPropertyHelper(缩写为OAPH)从当前 ViewModel 生成的可观察对象。

但是,在您的情况下,您的 observable/object 与当前 ViewModel 之外的对象相关。OAPH 本身是一个 Disposable 对象。

因此,您可以使用ISupportsActivation(很快会替换IActivableViewModel)并将您的 OAPH 传递给它的 Disposable 属性。

public class TestViewModel : ReactiveObject, ISupportsActivation
{
    private readonly ObservableAsPropertyHelper<bool> _status;
    public bool Status => _status.Value;
    public ViewModelActivator Activator { get; } = new ViewModelActivator();

    public TestViewModel(ILongLivedObject obj)
    {
         _status = obj.Status.ToProperty(this, vm => vm.Status);
         this.WhenActivated(disposables =>
         {
             disposables(_status);
         }
    }
}

disposables传递给lambda的参数WhenActivated是一个 Func,它接受一个IDisposable

在视图中,确保您派生出IActivatable(即将重命名IActivatableView)并在视图的构造函数中使用WhenActivated。


推荐阅读