3

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)

MrLuje
  • 637
  • 6
  • 15

1 Answers1

8

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;.)

domy
  • 113
  • 4
  • Thanks, that was it! I was also missing *interaction.SetOutput(Unit.Default);* in my RegisterHandler call so that I tell I handled the interaction. I find the double Subscribe syntax a bit weird, is there a cleaner way to write it ? – MrLuje Jul 05 '17 at 19:59
  • That mostly depends on the situation; if the surrounding code expects an `IObservable` to be returned, you usually don't need the `.Subscribe()` call on the interaction. For example, you could rewrite that line as `GetCmd.ThrownExceptions.SelectMany(ex => Interactions.Errors.Handle(ex)).Subscribe();`. [SelectMany](http://reactivex.io/documentation/operators/flatmap.html) in this case simply "pipes" the exceptions coming down the `ThrownExceptions` observable into the `Handle` observable, implicitly subscribing to the `Handle` observable. – domy Jul 05 '17 at 21:53