Improvement on First Windows 10 IoT Core Windows Application

Now that I have a working first application working, I wanted to see how far I can take the application writing model on the Raspberry Pi.

Our first Windows application is a WPF application.  Let see if we can leverage the full power of WPF and take it to the next level.

Why

WPF application will work with hardcoded event handlers on the page. But there is a better more comprehensive way to do WPF. It’s called MVVM.

Being a purist, I would much rather do things correctly. So I want to make sure WPF for Windows 10 IoT Core applications support MVVM.

MVVM is a bit overkill for this small application. But once our applications start becoming more and more complicated, MVVM will make things a lot easier to manage.

WPF, XAML and MVVM

Before we start, note that I will not go into details here. MVVM is a much wider and complicated field than what this little blog post can answer. I’m just going to give you a quick overview and provide you with an example. If you need more information feel free to google it.

MVVM (Model, View, ViewModel) is a design pattern. One of the most powerful feature of MVVM is that it can separate the UI from the functionality. MVVM is composed of 3 different components:

  • Model: Contains the data.
  • View: Provides a screen.
  • ViewModel: Provides the functionality.

WPF is particularly well suited for the MVVM pattern.

XAML is the View language for WPF application. XAML is a declarative language that can be edited completely separate from the actual functionality code. This means that the developers can write all the functionality, and then let the designers build the screen.

What we need for MVVM under WPF is:

  • Data Binding
  • Commanding support

My take on MVVM

You will notice that we do not implement a Model. That is because there is no real data our application manages.

Let’s get started:

Utility Classes

First I need a couple of utility classes to support Data Binding and Commands.

BaseVM: Implements the INotifyPropertyChanged interface so that the functionality (ViewModel) can notify the UI that something changed. Here is the code:

public class BaseVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        Debug.WriteLine("OnPropertyChanged: {0}", propertyName);
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

VMCommand: Implements the ICommand interface so that the UI can send commands to the functionality (ViewModel). Here is the code:

public delegate bool CanExecuteDelegate(object o);
public delegate void ExecuteDelegate(object o);

public class VMCommand : ICommand
{
    public VMCommand(ExecuteDelegate execute)
    {
        ExecuteFunction = execute;
        CanExecuteFunction = null;
    }

    public VMCommand(ExecuteDelegate execute, CanExecuteDelegate canexec)
    {
        ExecuteFunction = execute;
        CanExecuteFunction = canexec;
    }

    private ExecuteDelegate ExecuteFunction { get; set; }
    private CanExecuteDelegate CanExecuteFunction { get; set; }

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        bool result = true;
        if (CanExecuteFunction != null)
        {
            result = CanExecuteFunction(parameter);
        }
        return result;
    }

    public void Execute(object parameter)
    {
        if (ExecuteFunction != null)
        {
            ExecuteFunction(parameter);
        }
    }

    public void OnCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
        {
            CanExecuteChanged(this, new EventArgs());
        }
    }
}

ViewModel

Then I implemented the functionality in the ViewModel. Notice that:

  • The ViewModel truly represents the business. Its public members are: GreetingMessage, PersonName and GreetCommand.
  • The code implementation for the GreetExecute function is very simple, it reads/writes properties of the ViewModel and is not aware of controls on the View

Here is the code:

public class MainPageVM : BaseVM
{
    public MainPageVM()
    {
        InitializeCommands();
    }

    private string m_GreetingMessage = "Hello World!";
    public string GreetingMessage
    {
        get
        {
            return m_GreetingMessage;
        }
        set
        {
            if(value != m_GreetingMessage)
            {
                m_GreetingMessage = value;
                OnPropertyChanged();
            }
        }
    }

    private string m_PersonName = string.Empty;
    public string PersonName
    {
        get
        {
            return m_PersonName;
        }
        set
        {
            if (value != m_PersonName)
            {
                m_PersonName = value;
                OnPropertyChanged();
            }
        }
    }

    public VMCommand GreetCommand { get; set; }
    private void InitializeCommands()
    {
        GreetCommand = new VMCommand(GreetExecute);
    }

    private void GreetExecute(object o)
    {
        string greet = "Hello World!";
        if (!string.IsNullOrEmpty(PersonName))
        {
            greet = string.Format("Hello {0}!", PersonName);
        }
        GreetingMessage = greet;
    }

}

View

Then I wrote the XAML View. Notice that:

  1. We declare a ViewModel as a resource that we instantiate as the DataContext of the top Grid. This is how we access the ViewModel.
  2. The controls do not need to be named, because they are not referenced anywhere in the code.
  3. The Text properties of controls are bound to the ViewModel members. Because the ViewModel derives from BaseVM, the content of Text will change whenever the content of the ViewModel property changes. Also when the TextBox looses focus, it will automatically update the view model.
  4. Also there is no event handler on the Button instead there is a binding to the Command on the ViewModel.

Here is the code:

<Page
    x:Class="HelloWorld.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloWorld"
    xmlns:vm="using:HelloWorld.VM"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
    mc:Ignorable="d">
    <Page.Resources>
        <vm:MainPageVM x:Key="PageViewModel" />
    </Page.Resources>
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{StaticResource PageViewModel}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="51"/>
            <RowDefinition Height="51"/>
            <RowDefinition Height="51"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="1" Text="{Binding GreetingMessage}" HorizontalAlignment="Center"/>
        <TextBox Grid.Row="2" Text="{Binding PersonName, Mode=TwoWay}" HorizontalAlignment="Center" Margin="5" Width="150"/>
        <Button Grid.Row="3" Content="Greet" Command="{Binding GreetCommand}" HorizontalAlignment="Center" />
    </Grid>
</Page>

Testing

Now that our application is written, we will build and test it. First I tested it on my local machine. Then switched to Remote Debugging to test it on the Raspberry Pi.

Conclusion

MVVM is a very powerful model for writing WPF application. I am glad to see that the Windows 10 IoT Core application can support full WPF application written in MVVM.

This means we can create much more evolved and complicated applications more easily.

, , , , ,

  1. Leave a comment

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s

%d bloggers like this: