Friday, 22 November 2013

A GitHub Client with WPF and ReactiveUI Part 1

The View Models

Other posts in this series:

Part 2 – The Views



ReactiveUI is an awesome framework, but there’s a serious lack of documentation and examples on the net. So why not build a simple Github client using WPF and ReactiveUI.

You can find the source here on GitHub.

First of all, let’s display a login page. We’ll want this page to take up the whole of the application’s main window while the user is logging in and then disappear to be replaced by the real content.

image

(Hey, I didn’t say it’d be pretty)

In WPF, there’s a super useful control for contextually displaying views called ContentControl. You’d set a property on a view model, bind the ContentControl.Content property to this and depending on what type was assigned to the view model property, the ContentControl could select (via Data Templates) the correct view. The equivalent in ReactiveUI is the ViewModelViewHost control and it works somewhat similarly (but without Data Templates).

So lets start with the MainWindowViewModel:

public class MainWindowViewModel : ReactiveObject
{
    private ReactiveObject content;

    public MainWindowViewModel()
    {
        // Initially show the login view.
        this.content = new LoginViewModel();
    }

    public ReactiveObject Content
    {
        get { return this.content; }
        private set { this.RaiseAndSetIfChanged(ref this.content, value); }
    }
}

You’ll note that the view model inherits from ReactiveObject. This is the base class for – surprise - reactive objects in ReactiveUI. The RaiseAndSetIfChanged extension method helps keep the INotifyPropertyChanged boilerplate to a minimum. We have a Content property that is initially set to an instance of LoginViewModel:

public class LoginViewModel : ReactiveObject
{
    private string userName;
    private string password;

    public LoginViewModel()
    {
        // The login command is only enabled when both a user name and password have been 
        // entered.
        this.LoginCommand = new ReactiveCommand(
            this.WhenAny(
                x => x.UserName,
                x => x.Password,
                (userName, password) => 
                    !string.IsNullOrWhiteSpace(userName.Value) && 
                    !string.IsNullOrWhiteSpace(password.Value)));
    }

    public string UserName
    {
        get { return this.userName; }
        set { this.RaiseAndSetIfChanged(ref this.userName, value); }
    }

    public string Password
    {
        get { return this.password; }
        set { this.RaiseAndSetIfChanged(ref this.password, value); }
    }

    public ReactiveCommand LoginCommand
    {
        get;
        private set;
    }
}

In LoginViewModel we have the expected UserName and Password properties, together with a LoginCommand. This is the command that will be executed when the user clicks the OK button on the login form.

ReactiveUI’s magical WhenAny extension method sets up an Observable to ensure that the command should only be enabled when both a user name and password have been entered.

Pretty straightforward MVVM so far. In Part 2 we’ll create the views.

No comments:

Post a Comment