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
,除非:
- 您需要知道与此 ViewModel 关联的视图何时真正可见或从可视化树中删除
- 您正在订阅一个比您自己的对象寿命更长的对象(即订阅了
MessageBus
的 ListBoxItemViewModel
)
但老实说,与其每次点击按钮都创建一个新的 ViewModel,不如在 View 的构造函数中创建一个 ViewModel,然后将按钮绑定到 ReactiveCommand
。
我们一直在努力使 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
,除非:
- 您需要知道与此 ViewModel 关联的视图何时真正可见或从可视化树中删除
- 您正在订阅一个比您自己的对象寿命更长的对象(即订阅了
MessageBus
的ListBoxItemViewModel
)
但老实说,与其每次点击按钮都创建一个新的 ViewModel,不如在 View 的构造函数中创建一个 ViewModel,然后将按钮绑定到 ReactiveCommand
。