Simplifying ViewModels

Techniques that I use to make ViewModels simple include:

  • Automatic implementation of INotifyPropertyChanged interface (thanks to Simon Cropp's Fody: link)
  • Automatic method to ICommand conversion using conventions (thanks to Rob Eisenberg's Calliburn Micro: link)

I don't like too verbose code. For example, this is the code taken from the main page of very popular MVVM Framework - ReactiveUI:

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.