ReactiveUI 7.0交互处理程序从未被调用

3
所以,我正在学习如何在winforms中使用ReactiveUI 7.4,并且我认为我已经有了非常好的体验,直到我尝试包含交互来显示错误弹出窗口: 视图模型
public class ViewModel : ReactiveObject
{
    [...]

    public ViewModel()
    {
        GetCmd = ReactiveCommand.CreateFromTask(
            _ => myAsyncFunc(),
            CanGetCmd
        );

        GetCmd.ThrownExceptions
              .Subscribe(ex => Interactions.Errors.Handle(ex));   <- breakpoint correctly breaks in there
    }
}

交互

public static class Interactions
{
    public static readonly Interaction<Exception, Unit> Errors = new Interaction<Exception, Unit>();
}

查看

public ViewCtor()
{
    [viewmodel declaration...]

    this.btnGet.Events().Click
        .Select(_ => Unit.Default)
        .InvokeCommand(this, x => x.ViewModel.GetCmd);

    Interactions.Errors.RegisterHandler(interaction => 
    {
        _popupManager.Show(interaction.Input.Message, "Arf !");   <- but breakpoint never hits here :(
    });
}

基本上在调试中,断点会命中Handle声明,但从未命中RegisterHandler函数。
我可能遗漏了什么,因为根据ReactiveUI文档中关于交互的说明,如果我没有设置任何RegisterHandler(我已经尝试过),我应该得到一个UnhandledInteractionException,但我甚至没有得到这个异常...
如果给定交互没有处理程序,或者没有处理程序设置结果,则该交互本身被视为未处理。在这种情况下,调用Handle将导致抛出UnhandledInteractionException。
(我还使用reactiveui-events-winforms进行更好的事件语法绑定)
1个回答

8

Interactions.Errors.Handle(ex) 返回一个冷 Observable,即在订阅之前它并没有实际执行任何操作。下面这样应该可以正常工作:

GetCmd.ThrownExceptions
          .Subscribe(ex => Interactions.Errors.Handle(ex).Subscribe());

(您可能需要添加using System;。)

谢谢,就是这样!我在我的RegisterHandler调用中也漏掉了*interaction.SetOutput(Unit.Default);*,所以我告诉它我处理了交互。 我觉得双重订阅语法有点奇怪,有没有更简洁的写法? - MrLuje
这主要取决于情况;如果周围的代码期望返回一个 IObservable<T>,通常不需要在交互上调用 .Subscribe()。例如,您可以将该行重写为 GetCmd.ThrownExceptions.SelectMany(ex => Interactions.Errors.Handle(ex)).Subscribe();。在这种情况下,SelectMany 简单地将从 ThrownExceptions 可观察到的异常“管道化”到 Handle 可观察到的异常中,隐式订阅了 Handle 可观察对象。 - domy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接