public class NewUserViewModel : ReactiveObject
{
// This is ReactiveUI's version of implementing INotifyPropertyChanged
string _Password;
public string Password {
get { return _Password; }
set { this.RaiseAndSetIfChanged(x => x.Password, value); }
}
string _PasswordConfirmation;
public string PasswordConfirmation {
get { return _PasswordConfirmation; }
set { this.RaiseAndSetIfChanged(x => x.PasswordConfirmation, value); }
}
ICommand OkCommand { get; protected set; }
public NewUserViewModel()
{
// Here's the interesting part - we'll combine the change notifications
// for Password and PasswordConfirmation, and that will determine when
// we can hit the Ok button
//
// canHitOk is now a stream of True's and False's
var canHitOk = this.WhenAny(
x => x.Password,
x => x.PasswordConfirmation,
(pass, confirm) => (pass.Value == confirm.Value && pass.Value.Length > 3));
// Feed this to the canExecute of the OkCommand - now the button is
// bound to the two properties and will disable itself until the
// Func above is true.
OkCommand = new ReactiveCommand(canHitOk);
}
}
Frankly, this concrete example doesn't impress me at all. I can write the same code using techniques I mentioned at the beginning and it will look like this:
public class NewUserViewModel : PropertyChangedBase
{
public string Password { get; set; }
public string PasswordConfirmation { get; set; }
public bool CanOkCommand { get { return Password == PasswordConfirmation && Password.Length > 3 } }
public void OkCommand { /* and this handler is here as a bonus */ }
}
It behaves exactly the same (all PropertyChanged and CanExecuteChanged events will be emitted correctly).
Don't get me wrong. I like Rx very much and I'm not saying that using it is bad. It is exactly opposite. Using Rx is very helpful in many cases (of course inside ViewModels too). I just prefer to combine all available tools to resolve concrete problems. The goal is to achieve the greatest possible simplicity and readability.