ReactiveUI ToProperty异常

时间:2015-03-12 16:59:17

标签: c# system.reactive reactiveui

我们一直在努力让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的指导是什么?

例如,由于_output具有空值,因此在WhenActivated中没有绑定会导致Output属性的get属性中出现异常。鉴于需要长期运行的任务来填充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));

1 个答案:

答案 0 :(得分:1)

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

,否则您无需在ViewModel中使用WhenActivated
  1. 您需要知道与此ViewModel关联的视图何时实际可见或已从Visual Tree中删除
  2. 您正在订阅一个超过您自己的对象(即订阅ListBoxItemViewModel的{​​{1}})
  3. 但说实话,不是每次按下按钮都创建一个新的ViewModel,最好在View的构造函数中创建一个ViewModel,然后将按钮绑定到MessageBus