In addition to registering Interaction
handlers manually, we also provide a set of view extension methods for setting up bindings, both of which mimic the handler
parameter of the RegisterHandler
overloads:
IDisposable BindInteraction<TViewModel, TView, TInput, TOutput>(
this TView view,
TViewModel? viewModel,
Expression<Func<TViewModel, Interaction<TInput, TOutput>>> propertyName,
Func<InteractionContext<TInput, TOutput>, Task> handler);
IDisposable BindInteraction<TViewModel, TView, TInput, TOutput, TDontCare>(
this TView view,
TViewModel? viewModel,
Expression<Func<TViewModel, Interaction<TInput, TOutput>>> propertyName,
Func<InteractionContext<TInput, TOutput>, IObservable<TDontCare>> handler);
Registering handlers manually is fine for simple scenarios. But if, for example, you expect your Interaction
or one of its ancestors to change, the complexity starts increasing because of the need to dispose of the old and subscribe to the latest:
var interactionDisposable = new SerialDisposable();
this
.WhenAnyValue(x => x.ViewModel.MyInteraction)
.Where(x => x != null)
.Do(x => interactionDisposable.Disposable = x.RegisterHandler(context => /*Do Something*/))
.Finally(() => interactionDisposable?.Dispose())
.Subscribe();
Compare that with the binding approach...
// In a view
this.BindInteraction(
this.ViewModel,
vm => vm.MyInteraction,
context => /*Do Something*/);
and it's clear to see the benefits.
Just like the rest of the Bind
family, it's easy to "unhook" the binding by disposing of the returned IDisposable
object. If you're using the WhenActivated
feature, it's simply:
this.WhenActivated(
disposables =>
{
this.BindInteraction(
this.ViewModel,
vm => vm.MyInteraction,
context => /*Do Something*/)
.DisposeWith(disposables);
});