Search code examples
c#winformsreactiveuiinteraction

ReactiveUI 7.0 interaction handler never called


So, I am learning to use ReactiveUI 7.4 with winforms and I thing I got a pretty good experience with it until I tried to include Interactions for displaying an error popup :

ViewModel

public class ViewModel : ReactiveObject
{
    [...]

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

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

Interactions

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

View

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 :(
    });
}

Basically in debug, breakpoint hits in Handle declaration but never in RegisterHandler function.

I am probably missing something because from ReactiveUI documentation on interactions, I should get an UnhandledInteractionException if I don't set any RegisterHandler (which I tried) and I'm not even getting this exception...

If there are no handlers for a given interaction, or none of the handlers set a result, the interaction is itself considered unhandled. In this circumstance, the invocation of Handle will result in an UnhandledInteractionException being thrown.

(I am also using reactiveui-events-winforms for better event syntax wire up)


Solution

  • Interactions.Errors.Handle(ex) returns a cold observable, i.e. it doesn't actually do anything until you subscribe to it. This should work:

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

    (You may need to add using System;.)