Howto let ReactiveCommands observe their own IsExecuting observable
Asked Answered
I

1

5

I have several commands in my ViewModel and I want to have the CanExecute of each button to be bound to an observable busy which is defined as none of the buttons is currently executing.

The following is what I came up with, but obviously it runs into a NullReferenceException.

busy = Observable.CombineLatest(this.PlayCommand.IsExecuting, this.PauseCommand.IsExecuting, (play, pause) => play && pause);

this.PauseCommand = new ReactiveCommand(busy.Select(b => !b));
this.PlayCommand = new ReactiveCommand(busy.Select(b=> !b));

Also the CanExecuteObservable property on ReactiveCommand is readonly, so I need to define an IObservable before I initialize the commands.

Any ideas on how to solve this chicken and egg problem? A better way of observing busy state for a ViewModel (or a collection of ViewModels) would be appreciated also :-)

Interplead answered 27/4, 2014 at 11:41 Comment(0)
T
8

I would set up a proxy via using a Subject:

var areAllAvailable = new BehaviorSubject<bool>(true);

PauseCommand = new ReactiveCommand(areAllAvailable);
PlayCommand = new ReactiveCommand(areAllAvailable);

Observable.CombineLatest(PauseCommand.IsExecuting, PlayCommand.IsExecuting, 
    (pa,pl) => !(pa || pl))
    .Subscribe(allAreAvailable);
Tramway answered 27/4, 2014 at 20:54 Comment(2)
Great, works nicely. Never thought of that, I'll just blame the 'subjects are bad'-mantra that's going around :-). Also, the last line should include .Subscribe(n => areAllAvailable.OnNext(n)) to update the subject.Interplead
Subjects aren't necessarily 'bad', they're just not very Functional. They're actually really good for adapting existing code to Rx, since that code might not be Functional either!Tramway

© 2022 - 2024 — McMap. All rights reserved.