ReactiveUI ToProperty 异常

ReactiveUI ToProperty exceptions

我们一直在努力使 ToProperty 正常工作,但遇到了未被 ThrownExceptions 捕获的异常。

我们的测试视图模型如下所示:

    public class ViewModel : ReactiveObject, ISupportsActivation
{
    private readonly ViewModelActivator _activator = new ViewModelActivator();

    public ViewModelActivator Activator
    {
        get { return _activator; }
    }

    private ObservableAsPropertyHelper<String> _output;

    public string Output
    {
        get { return _output.Value; }
    }

    public ViewModel()
    {
        this.WhenActivated(delegate(Action<IDisposable> action)
        {
            action(
                Run()
                    .ToObservable()
                    .ToProperty(this, vm => vm.Output, out _output, "INIT", RxApp.MainThreadScheduler)
                    .ThrownExceptions.Subscribe(ex => Debug.WriteLine("Exception {0}", ex.Message)));
        });
    }

    public async Task<string> Run()
    {
        Debug.WriteLine("Running : Begin");

        await Task.Delay(5000);
        throw new InvalidOperationException("no way hosay");

        Debug.WriteLine("Running : End");
        return "Assigned";
    }
}

我们的视图看起来有点简单

public sealed partial class MainPage : Page,IViewFor<ViewModel>
{
    public MainPage()
    {
        this.InitializeComponent();

        this.NavigationCacheMode = NavigationCacheMode.Required;

        this.WhenActivated(d => 
        {
           d(this.OneWayBind(ViewModel, vm => vm.Output, v => v.Text.Text));
        });
    }

    object IViewFor.ViewModel
    {
        get { return ViewModel; }
        set { ViewModel = (ViewModel)value; }
    }

    public ViewModel ViewModel
    {
        get { return (ViewModel)GetValue(ViewModelProperty); }
        set { SetValue(ViewModelProperty, value); }
    }

    public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register("ViewModel", typeof(ViewModel), typeof(MainPage), new PropertyMetadata(null));

    private void BindButton_OnClick(object sender, RoutedEventArgs e)
    {
        this.ViewModel = new ViewModel();
    }

}

现在,如果他快速连续几次点击 'BindButton',我们会得到一个未被 ThrownExceptions 捕获的异常。

这是为什么?

此外,关于 ToProperty 的使用指南是什么?

例如,在 WhenActivated 中没有绑定会导致输出 属性 的获取 属性 出现异常,因为 _output 具有空值。考虑到可能需要很长的 运行 任务来填充 ToProperty 值,这是应该遵循的典型结构?

编辑:

通过对视图模型进行此更改,我们现在遇到的情况是我们似乎总是捕获异常,这是为什么?

var exec = Run().ToObservable();
_output = exec.ToProperty(this, x => x.Output, "INIT", RxApp.MainThreadScheduler);
_output.ThrownExceptions.Subscribe(ex => Debug.WriteLine("Exception {0}", ex.Message));

您看到这些异常的原因是您在 ViewModel 中使用 WhenActivated,并且这些 VM 在任务完成之前被删除。您不需要在 ViewModel 中使用 WhenActivated,除非:

  1. 您需要知道与此 ViewModel 关联的视图何时真正可见或从可视化树中删除
  2. 您正在订阅一个比您自己的对象寿命更长的对象(即订阅了 MessageBusListBoxItemViewModel

但老实说,与其每次点击按钮都创建一个新的 ViewModel,不如在 View 的构造函数中创建一个 ViewModel,然后将按钮绑定到 ReactiveCommand