The MVVM pattern – Dependency injection

In the previous posts we’ve learned the basic concepts of the MVVM pattern and how to apply them in a real application. In this post we’ll introduce some more advanced concepts, which will be helpful to implement the MVVM pattern in real and complex projects. We will do it by building a sample application slightly more complex than the one we built in the previous post.

Let’s create a feed reader

To understand what is the dependency injection mentioned in the title of the post we’re going to create an application which will show to the user a list of news retrieved from a RSS feed. As we did in the previous post, the first step is to split the application in the three main components:

  • The model, which is the base entity that identifies a news from the feed.
  • The view, which is the XAML page that will display the news using a ListView control.
  • The ViewModel, which will take care of retrieving the news from the RSS feed and pass it to the View.

Since the goal of the MVVM pattern is to separate, as much as possible, the different layers of the application, it’s a good practice to avoid including the logic required to parse the RSS feed directly in the ViewModel. A better approach is to handle this task to a specific class (we will call it RssService), which will take care of downloading the XML of the RSS feed, turn it into a collection of objects and return it to the ViewModel.

Let’s start with the model and define a class, called FeedItem, which identifies a single news from the feed:

public class FeedItem
{

    public string Title { get; set; }

    public string Description { get; set; }

    public string Link { get; set; }

    public string Content { get; set; }

    public DateTime PublishDate { get; set; }
}

Now we can create the service that, by leveraging LINQ to XML (a powerful language to manipulate XML files included into the framework .NET), is able to parse the RSS feed and convert it into a collection of FeedItem objects:

public class RssService: IRssService
{
    public async Task<List<FeedItem>> GetNews(string url)
    {
        HttpClient client = new HttpClient();
        string result = await client.GetStringAsync(url);
        var xdoc = XDocument.Parse(result);

        return (from item in xdoc.Descendants("item")
        select new FeedItem
        {
            Title = (string)item.Element("title"),
            Description = (string)item.Element("description"),
            Link = (string)item.Element("link"),
            PublishDate = DateTime.Parse((string)item.Element("pubDate"))
        }).ToList();
    }
}


The RssService class has an asynchronous method which uses the HttpClient class and its GetStringAsync() method to download the content of the RSS feed. Then, by using LINQ to XML, we convert the XML into a collection of FeedItem objects: every single node of the XML file (like title, description, link, etc.) is stored into a property of the FeedItem object.

Now we have a class that accepts the URL of a RSS feed in input and returns a list of FeedItem objects, that we can manipulate inside the ViewModel. Here is how the ViewModel of the page that displays the news looks like:

public class MainViewModel: ViewModelBase
{

    private List<FeedItem> _news;

    public List<FeedItem> News
    {
        get { return _news; }
        set { Set(ref _news, value); }
    }

    private RelayCommand _loadCommand;

    public RelayCommand LoadCommand
    {

        get
        {
            if (_loadCommand == null)
            {
                _loadCommand = new RelayCommand(async () =>
                {
                    RssService rssService = new RssService();
                    List<FeedItem> items = await rssService.GetNews("http://wp.qmatteoq.com/rss");
                    News = items;
                });
            }

            return _loadCommand;
        }
    }
}

We have reused the knowledge acquired in the previous posts to:

  1. Define a property called News, which type is List<FeedItem>, where we’re going to store the list of news, that we will display in the page.
  2. We have defined a command, which we can connect to an event (like the button’s click), that creates a new instance of the RssService class and call the GetNews() method.

In the end, we can create the XAML page:

<Page
    x:Class="MVVMLight.Advanced.Views.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    DataContext="{Binding Source={StaticResource ViewModelLocator}, Path=Main}"
    mc:Ignorable="d">

       <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <ListView ItemsSource="{Binding Path=News}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding Path=PublishDate}" Style="{StaticResource SubtitleTextBlockStyle}" />
                            <TextBlock Text="{Binding Path=Title}" Style="{StaticResource TitleTextBlockStyle}" />
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>

    <Page.BottomAppBar>
        <CommandBar>
            <CommandBar.PrimaryCommands>
                <AppBarButton Icon="Refresh" Label="Load" Command="{Binding Path=LoadCommand}" />
            </CommandBar.PrimaryCommands>
        </CommandBar>
    </Page.BottomAppBar>
</Page>


In the page we added:

  1. A ListView control, which ItemsSource property is connected, using binding, to the News property of the ViewModel. When the ViewModel uses the RssService method to load into the News property the list of news, the control will update its visual layout to display them. Specifically, we have defined an ItemTemplate which shows the publishing date of the news and the title.
  2. An AppBarButton in the application bar, which is connected to the LoadCommand propert. When the button is pressed, the ViewModel will download the news from the RSS feed using the RssService class.

Now that we have our new sample application up & running we can introduce some new concepts that will help us to make it better.

Dependency injection

Let’s say that, at some point, we need to replace the RssService class with another one that, instead of retrieving the data from a real RSS feed, generates some fake data to display inside the app. There are many reasons to do it: for example, a designer may have the requirement to work on the user interface and he needs to simulate some “borderline” scenarios, like a news with a very long title. Or maybe our application handles more complex data and, instead of a RSS feed, we have a database or a cloud service which can be hard to configure just for test purposes.

In our sample application, it isn’t that hard to accomplish this goal. We just need to create a new class (for example, FakeRssService) which returns a set of fake FeedItem objects, like the following one:

public class FakeRssService
{
    public Task<List<FeedItem>> GetNews(string url)
    {
        List<FeedItem> items = new List<FeedItem>
        {
            new FeedItem
            {
                PublishDate = new DateTime(2015, 9, 3),
                Title = "Sample news 1"
            },
            new FeedItem
            {
                PublishDate = new DateTime(2015, 9, 4),
                Title = "Sample news 2"
            },
            new FeedItem
            {
                PublishDate = new DateTime(2015, 9, 5),
                Title = "Sample news 3"
            },
            new FeedItem
            {
                PublishDate = new DateTime(2015, 9, 6),
                Title = "Sample news 4"
            }
        };

        return Task.FromResult(items);
    }
}

Then we just need to change the code executed when the LoadCommand is execute to use this new class as replacement of the old one:

private RelayCommand _loadCommand;

public RelayCommand LoadCommand
{

    get
    {
        if (_loadCommand == null)
        {
            _loadCommand = new RelayCommand(async () =>
            {
                FakeRssService rssService = new FakeRssService ();
                List<FeedItem> items = await rssService.GetNews("http://wp.qmatteoq.com/rss");
                News = new ObservableCollection<FeedItem>(items);
            });
        }
        
        return _loadCommand;
    }
}

Up to now, things are quite simple. However, let’s say that we’re working on a more complex application which, instead of having one single page that uses the RssService class, has 30 pages, which means that we have 30 ViewModels that are using the RssService class. Consequently, when we need to replace it with the fake one we’ve just created, we need to edit every single ViewModel and change the used class. You can easily imagine how this approach is time consuming and, most of all, makes easier to introduce errors. It’s enough to forget to replace back the original class in one of the ViewModels when we have finished the testing phase to create a big issue.

Let’s introduce the dependency injection concept, which is a way to handle this scenario in a better way. The problem I have just described raises from the fact that, in the previous approach, the RssService class (which we can consider it as a dependency of the ViewModel, since it can’t work properly without it) was created at build time. With dependency injection, we change approach and we start to solving these dependencies at runtime, when the application is running.

This is possible thanks to a special class, called container, that we can consider like a box: inside it, we’re going to register all the ViewModels and all the dependencies that are required by our application. When the application is running and we need a new instance of a ViewModel (simply because the user is navigating to a new page), we won’t create it anymore manually, but we will ask to the container to do it for us. The container will check if it’s able to solve all the dependencies (which means that all the services used by the ViewModels are available) and, if the answer is yes, it will return to us a new instance of the ViewModel with all the dependencies already solved and ready to be used. Technically speaking, we say that the dependencies are “injected” into to the ViewModel: this is why this technique is called dependency injection.

Why does this approach solve the previous problem, which is avoid to change all the ViewModels if we need to change the implementation of a service? Because the connection between the ViewModel and the service is handled by the container, which is a single instance across the whole application. Every ViewModel won’t have anymore to manually create a new instance of the RssService class, but it will be automatically included in the ViewModel’s constructor. It’s the container’s job to create a new instance of the RssService class and pass it to the ViewModel, so that it can use it. When we need to replace the RssService class with the FakeRssService one, we just need to change the class registered in the container and, automatically, all the ViewModels will start to use the new one.

To properly support this approach, there are a couple of changes we need to make to our application. Let’s see them.

Define an interface

The first problem in our code is that RssService is a class and, as such, we don’t have a way to easily swap it with another one in the container. To do it, we need something that describes in an abstract way the RssService class and the operation that it can perform, so that we can leverage it both in the RssService and in the FakeRssService classes. This is what interfaces are for: their purpose is to describe a set of properties and methods which, in the end, will be implemented by a real class. The first step, consequently, is to create an interface which describes the operations performed by our RSS service. The same interface will be implemented both by the real service (the RssService class) and the fake one (the FakeRssService class). After we’ve done this modify, we’ll be able to:

  1. Reference the service in the ViewModel using the interface instead of the real class.
  2. Register in the container the connection between the interface and the real class that we want to use. At runtime, the container will inject into the ViewModel the implementation we have chosen. If we want to swap it, we just need to register in the container another class for the same interface.

Let’s start by creating an interface and call it IRssService:

public interface IRssService
{
    Task<List<FeedItem>> GetNews(string url);
}

Our service, for the moment, exposes just one asynchronous operation: GetNews(), which takes as input the URL of the RSS feed and returns, as ouput, a collection of FeedItem objects.

Now we need to change our classes RssService and FakeRssService to implement this interface, like in the following example:

public class RssService : IRssService
{

    public async Task<List<FeedItem>> GetNews(string url)
    {
        HttpClient client = new HttpClient();
        string result = await client.GetStringAsync(url);
        var xdoc = XDocument.Parse(result);
        return (from item in xdoc.Descendants("item")
                select new FeedItem
                {
                    Title = (string)item.Element("title"),
                    Description = (string)item.Element("description"),
                    Link = (string)item.Element("link"),
                    PublishDate = DateTime.Parse((string)item.Element("pubDate"))
                }).ToList();
    }
}

public class FakeRssService : IRssService
{
    public Task<List<FeedItem>> GetNews(string url)
    {
        List<FeedItem> items = new List<FeedItem>
    {
        new FeedItem
        {
            PublishDate = new DateTime(2015, 9, 3),
            Title = "Sample news 1"
        },
        new FeedItem
        {
            PublishDate = new DateTime(2015, 9, 4),
            Title = "Sample news 2"
        },
        new FeedItem
        {
            PublishDate = new DateTime(2015, 9, 5),
            Title = "Sample news 3"
        },
        new FeedItem
        {
            PublishDate = new DateTime(2015, 9, 6),
            Title = "Sample news 4"
        }
    };

        return Task.FromResult(items);
    }
}

As you can see, both services are using the same interface and they are implementing the same method: the only difference is that the RssService class is returning real data, while the FakeRssService one is manually creating a set of fake FeedItem objects.

The ViewModel

There are a couple of changes we need to apply to our ViewModel:

  1. We don’t need anymore to manually create a new instance of the RssService class in the command, but we need to add it as parameter in the ViewModel’s constructor. We need to reference the IRssService interface, otherwise we won’t be able to easily swap between its different implementations.
  2. We need to change the LoadCommand, in order to use this new instance of the service.

Here is how our updated ViewModel looks like:

public class MainViewModel : ViewModelBase
{
    private readonly IRssService _rssService;

    public MainViewModel(IRssService rssService)
    {
        _rssService = rssService;
    }

    private ObservableCollection<FeedItem> _news;

    public ObservableCollection<FeedItem> News
    {
        get { return _news; }
        set { Set(ref _news, value); }
    }

    private RelayCommand _loadCommand;

    public RelayCommand LoadCommand
    {
        get
        {
            if (_loadCommand == null)
            {
                _loadCommand = new RelayCommand(async () =>
                {                
                    List<FeedItem> items = await _rssService.GetNews("http://wp.qmatteoq.com/rss");
                    News = new ObservableCollection<FeedItem>(items);
                });
            }

            return _loadCommand;
        }
    }
}

The ViewModelLocator

The last step is also the most important one, which is creating the container and registering into it all the ViewModels with their dependencies. Typically this configuration is done when the app starts so, when we use MVVM Light and the ViewModelLocator approach, the best place where to do it is the ViewModelLocator itself, since it’s the class that takes care of dispatching all the ViewModels.

Here is our new ViewModeloLocator implementation looks like:

public class ViewModelLocator
{

    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        
        SimpleIoc.Default.Register<IRssService, RssService>();
        SimpleIoc.Default.Register<MainViewModel>();
    }

    public MainViewModel Main
    {
        get { return ServiceLocator.Current.GetInstance<MainViewModel>(); }
    }
}

First of all, we need to higlight that this code is just a sample: there are plenty of available libraries to implement the dependency injection approach, like Ninject or LightInject. However, most of the MVVM toolkits and frameworks provide also an infrastructure to handle this scenario and MVVM Light makes no exception, by providing a simple container identified by the SimpleIoc class, which is set as default container of the app by using the SetLocationProvider() of the ServiceLocator class.

The next step is to register all the ViewModels and theri dependencies in the container. The SimpleIoc class offers the Register() method to achieve this goal, which can be used in two ways:

  1. The Register<T>() version, which is used when we just need to a new instance of a class which isn’t described by an interface. It’s the case of our ViewModels since, in our context, we don’t need a way to completely swap them.
  2. The Register<T, Y>() version, which is used, instead, when we need to register a class that is described by an interface. In this case, we specify as T the interfance and as Y the implementation we want to use.

In the end, we need to change the way the ViewModelLocator class defines the Main property: instead of manually creating a new MainViewModel object, we ask to the container to give us a new instance of the class, by using the GetInstance<T> method (where T is the type we need).

After we have done these changes, here is what we’ll happen when we’ll launch our application again:

  1. The application will create a new instance of the ViewModelLocator class, which will start the configuration of the container. The SimpleIoc class will register the MainViewModel and the RssService classes (the second one, described by the IRssService interface).
  2. The application will trigger the navigation to the main page of the app. Consequently, since the DataContext property of the Page is connected to the Main property of the ViewModelLocator, the locator will try to create a new instance of the ViewModel.
  3. The container defined in the ViewModelLocator class will check if there’s a class which type is MainViewModel registered. The answer is yes, however the class depends from a class that implements the IRssService interface. Consequently, the container will start another search and it will check if there’s a class connected to teh IRssService interface registered. Also in this case the answer is yes: the container will return a new instance of the MainViewModel class with the RssService implementation ready to be used.

If any of the previous conditions isn’t satisfied (for example, the container doesn’t find a class registered for the IRssService interface), we will get an exception, since the container wasn’t able to resolve all the dependencies. Now that we have reached the end of the journey, you should be able to understand why the depenncy injection is extremely useful for our scenario. As soon as we need to do some tests and we want to use the FakeRssService class in replacement of the RssService one, we juest need to change one line of code in the ViewModelLocator class. Instead of:

SimpleIoc.Default.Register<IRssService, RssService>();

we would need to do :

SimpleIoc.Default.Register<IRssService, FakeRssService>();

Thanks to this new approach, it doesn’t matter if our application has just one ViewModel or 50 ViewModels which are dependening from the IRssService interface: automatically, the container will take care of injecting the proper real class to any of them.

This approach is extremely useful not just when you’re doings tests, but also if you need to perform heavy refactoring. Let’s say that, at some point, our application doesn’t have to retrieve the news from a RSS feed anymore, but from a REST service published on the cloud. As long as our new service will follow the same structure defined by the IRssService interface (in our case, a GetNews() method which returns a collection of FeedItem objects) we won’t have to change anything in the ViewModels. We just need to create a new class which implements the IRssService interface and register it into the container, in replacement of the RssService one.

In the next post

We’re reaching the end of our learning path. In the next post we’re going to see some other advances scenarios, like sending messages and handling secondary events. As usual, you can play with the sample project described in this post on GitHub: https://github.com/qmatteoq/UWP-MVVMSamples Happy coding!

Introduction to MVVM – The series

  1. Introduction
  2. The practice
  3. Dependency Injection
  4. Advanced scenarios
  5. Services, helpers and templates
  6. Design time data
Posted in Universal Apps, UWP, wpdev | Tagged , , | Leave a comment

The MVVM pattern – The practice

Let’s continue our journey to learn the MVVM pattern, applied to Universal Windows apps development. After we’ve learned the basic concepts in the previous post, now it’s time to start writing some code. As already mentioned in the previous post, we’re going to leverage MVVM Light as toolkit to help us implementing the pattern: since it’s the most flexible and simple to use, it will be easier to understand and apply the basic concepts we’ve learned so far.

The project

The goal of the MVVM pattern is to help developers to organize their code in a better way. As such, the first step is to define the structure of a project in a way that, also from a logical point of view, it can follow the principles of the pattern. Consequently, usually the first thing to do is to create a set of folders where to place our classes and files, like:

  • Models, where to store all our basic entities.
  • ViewModels, where to store the classes that will connect the Model with the View.
  • Views, where to store the Views, which are the XAML pages in case of a Universal Windows app.

In a typical MVVM project, however, you will end up to have more folders: one of the assets, one for the services, one for the helper classes, etc.

The second step is to install in the project the library we have chosen to help us implementing the pattern. In our case, we chose MVVM Light, so we can leverage NuGet to install it. We will find two different versions:

For the moment, my suggestion is to use the second package: this way, we will do everything from scratch, giving us the chance to better learn the basic concepts. In the future, you’re free to use the first package if you want to save some time.

As a sample project, we’re going to create a very simple Universal Windows app that it’s likely you would be able to develop in no time using code behind: a Hello World app with a TextBox, where to insert your name, and a Button that, when it’s pressed, will display a hello message followed by your name.

Linking the View and ViewModel

The first step is to identify the three components of our application: Model, View and ViewModel.

  • The model isn’t necessary in this application, since we don’t need to manipulate any entity.
  • The view will be made by a single page, which will show to the user the TextBox where to insert his name and the Button to show the message.
  • The ViewModel will be a class, which will handle the interaction in the view: it will retrieve the name filled by the user, it will compose the hello message and it will display it in the page.

Let’s start to add the various components: let’s create a Views folder and add, inside it, the only page of our application. As default behavior, when you create a new Universal Windows app the template will create a default page for you, called MainPage.xaml. You can move it to the Views folder or delete it and create a new one in Solution Explorer by right clicking on the folder and choosing Add –> New item –> Blank page.

Now let’s create the ViewModel that will be connected to this page. As explained in the previous post, the ViewModel is just a simple class: create a ViewModels folder, right click on it and choose Add –> New Item –> Class.

Now we need to connect the View and the ViewModel, by leveraging the DataContext property. In the previous post, in fact, we’ve learned that the ViewModel class is set as DataContext of the page; this way, all the controls in the XAML page will be able to access to all the properties and commands declared in the ViewModel. There are various ways to achieve our goal, let’s see them.

Declare the ViewModels as resources

Let’s say that you have created a ViewModel called MainViewModel. You’ll be able to declare it as a global resource in the App.xaml file this way:

<Application
    x:Class="MVVMSample.MVVMLight.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="using:MVVMSample.MVVMLight.ViewModel">

    <Application.Resources>
        <viewModel:MainViewModel x:Key="MainViewModel" />
    </Application.Resources>

</Application>

The first step is to declare, as attribute of the Application class, the namespace which contains the ViewModel (in this sample, it’s MVVMSample.MVVMLight.ViewModel). Then, in the Resources collection of the Application class, we declare a new resource which type is MainViewModel and we associate it to a key with the same name. Now we can use this key and the StaticResource keyword to connect the DataContext of the page to the the resource, like in the following sample:

<Page
    x:Class="MVVMSample.MVVMLight.Views.MainPage"
    DataContext="{Binding Source={StaticResource MainViewModel}}"
    mc:Ignorable="d">

    <!-- your page content -->

</Page>

The ViewModelLocator approach

Another frequently used approach is to leverage a class called ViewModelLocator, which has the responsability of dispatching the ViewModels to the various pages. Instead of registering all the ViewModels as global resources of the application, like in the previous approach, we register just the ViewModelLocator. All the ViewModels will be exposed, as properties, by the locator, which will be leveraged by the DataContext property of the page.

This is a sample definition of a ViewModelLocator class:

public class ViewModelLocator
{
    public ViewModelLocator()
    {
    }

    public MainViewModel Main
    {
        get
        {
            return new MainViewModel();
        }
    }
}

Or, as an alternative, you can simplify the code by leveraging one of the new C# 6 .0 features:

public class ViewModelLocator
{
    public ViewModelLocator()
    {
    }

    public MainViewModel Main => new MainViewModel();
}

After you’ve added the ViewModelLocator class as global resource, you’ll be able to use it to connect the Main property to the DataContext property of the page, like in the following sample:

<Page
    x:Class="MVVMSample.MVVMLight.Views.MainPage"
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    mc:Ignorable="d">

    <!-- your page content -->

</Page>

The syntax is very similar to the one we’ve seen with the first approach; the main difference is that, since the ViewModelLocator class can expose multiple properties, we need to specify with the Path attribute which one we want to use.

The ViewModelLocator’s approach adds a new class to maintain, but it gives you the flexibilty to handle the ViewModel’s creation in case we need to pass some parameters to the class’ constructor. In the next post, when we’ll introduce the dependeny injection’s concept, it will be easier for you to understand the advantages in using the ViewModelLocator approach.

Let’s setup the ViewModel

No matter which approach we decided to use in the previous step, now we have a View (the page that will show the form to the user) connected to a ViewModel (the class that will handle the user’s interactions).

Let’s start to populate the ViewModel and to define the properties that we need to reach our goal. In the previous post we’ve learned that ViewModels need to leverage the INotifyPropertyChanged interface; otherwise, every time we change the value of a property in the ViewModel, the View won’t be able to detect it and the user won’t see any change in the user interface.

To make easier to implement this interface, MVVM Light offers a base class which we can leverage in our ViewModels using inheritance, like in the following sample:

public class MainViewModel : ViewModelBase
{

}

This class gives us access to a method called Set(), which we can use when we define our propeties to dispatch the notifications to the user interface when the value changes. Let’s see a sample related to our scenario. Our ViewModel has to be able to collect the name that the user has filled into a TextBox control in the View. Consequently, we need a property in our ViewModel to store this value. Here is how it looks like thanks to the MVVM Light support:

private string _name;

public string Name
{
    get
    {
        return _name;
    }

    set
    {
        Set(ref _name, value);
    }
}

The code is very similar to the one we’ve seen in the previous post when we introduced the concept of the INotifyPropertyChanged interface. The only difference is that, thanks to the Set() method, we can achieve two goals at the same time: storing the value in the Name property and dispatching a notification to the binding channel that the value has changed.

Now that we have learned how to create properties, let’s create another one to store the message that we will display to the user after he has pressed the button.

private string _message;

public string Message
{
    get
    {
        return _message;
    }

    set
    {
        Set(ref _message, value);
    }
}

In the end, we need to handle the interaction with the user. When he presses the Button in the view, we have to display a hello message. From a logical point of view, this means:

  1. Retrieving the value of the Name property.
  2. Leveraging the string interpolation APIs to prepare the message (something like “Hello Matteo”).
  3. Assign the result to the Message property.

In the previous post we’ve learned that, in the MVVM pattern, you use commands to handle the user interactions in a ViewModel. As such, we’re going to use another one of the classes offered by MVVM Light, which is RelayCommand. Thanks to this class, instead of having to create a new class that implements the ICommand interface for each command, we can just declare a new one with the following code:

private RelayCommand _sayHello;

public RelayCommand SayHello
{
    get
    {
        if (_sayHello == null)
        {
            _sayHello = new RelayCommand(() =>
            {
                Message = $"Hello {Name}"; 
            });
        }
            
        return _sayHello;
    }
}

When you create a new RelayCommand object you have to pass, as parameter, an Action, which defines the code that you want to execute when the command is invoked. The previous sample declares an Action using an anonymous method. It means that, instead of defining a new method in the class with a specific name, we define it inline in the property definition, without assigning a name.

When the command is invoked, we use the new C# 6.0 feature to perform string interpolation to get the value of the property Name and add the prefix “Hello”. The result is stored into the Message property.

Create the view

Now that the ViewModel is ready, we can move on and create the View. The previous step should have helped you to understand one of the biggest benefits of the MVVM pattern: we’ve been able to define the ViewModel to handle the logic and the user interaction without writing a single line of code in the XAML file. With the code behind approach, it would have been impossible; for example, if we wanted to retrieve the name filled in the TextBox property, we should have first added the control in the page and assign to it a name using the x:Name property, so that we would have been able to access to it from code behind. Or if we wanted to define the method to execute when the button is pressed, we would have needed to add the Button control in the page and subscribe to the Click event.

From a user interface point of view, the XAML we need to write for our application is more or less the same we would have created for a code behind app. The UI, in fact, doesn’t have any connection with the logic, so the way we create the layout doesn’t change when we use the MVVM pattern. The main difference is that, in a MVVM app, we will use binding a lot more, since it’s the way we can connect the controls with the properties in the ViewModel. Here is how our View looks like:

<Page
    x:Class="MVVMSample.MVVMLight.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
    mc:Ignorable="d">

    <Grid>
        <StackPanel Margin="12, 30, 0, 0">
            <StackPanel Orientation="Horizontal" Margin="0, 0, 0, 30">
                <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="300" Margin="0, 0, 20, 0" />
                <Button Command="{Binding Path=SayHello}" Content="Click me!" />
            </StackPanel>

            <TextBlock Text="{Binding Path=Message}" Style="{StaticResource HeaderTextBlockStyle}" />
        </StackPanel>
    </Grid>

</Page>

We have added to the page three controls:

  1. A TextBox, where the user can fill his name. We have connected it to the Name property of the ViewModel. There are two features to higlight:
    1. We have set the Mode attribute to TwoWay. It’s required since, for this scenario, we don’t just need that when the property in the ViewModel changes the control displays the updated value, but also the opposite. When the user fills some text in the control, we need to store its value in the ViewModel.
    2. We have set the UpdateSourceTrigger attribute to PropertyChanged. This way, we make sure that, every time the text changes (which means every time the user adds or remove a char in the TextBox), the Name property will automatically update to store the changed value. Without this attribute, the value of the property would be updated only when the TextBox control loses the focus.
  2. A Button, that the user will click to see the hello message. We have connected it to the SayHello command in the ViewModel.
  3. A TextBlock, where the user will see the hello message. We have connected it to the Message property of the ViewModel.

If we have done everything properly and we launch the app, we should see the application behaving as we described at the beginning of this post: after filling your name and pressing the button, you will see the hello message.

Let’s improve the user interaction

Our application has a flaw: if the user presses the button without writing anything in the TextBox, he would see just the “Hello” prefix. We want to avoid this behaviro by disabling the button if the TextBox control is empty. To achieve our goal we can leverage one of the features offered by the ICommand interface: we can define when a command should be enabled or not. For this scenario the RelayCommand class allows a second parameter during the initialization, which is a function that returns a boolean value. Let’s see the sample:

private RelayCommand _sayHello;

public RelayCommand SayHello
{
    get
    {
        if (_sayHello == null)
        {
            _sayHello = new RelayCommand(() =>
            {
                Message = $"Hello {Name}";
            },

            () => !string.IsNullOrEmpty(Name));
        }

        return _sayHello;
    }
}

We’ve changed the initialization of the SayHello command to add, as a second parameter, a boolean value: specifically, we check if the Name property is null or empty (in this case, we return false, otherwise true). Thanks to this change, now the Button control connected to this command will be automatically disabled (also from a visual point of view) if the Name property is empty. However, there’s a catch: if we try the application as it is, we would notice that the Button will be disabled by default when the app starts. It’s the expected behavior, since when the app is launched the TextBox control is emtpy by default. However, if we start writing something in the TextBox, the Button will continue to be disabled. The reason is that the ViewModel isn’t able to automatically determine when the execution of the SayHello command needs to be evaluated again. We need to do it manually every time we do something that may change the value of the boolean function; in our case, it happens when we change the value of the Name property, so we need to change the property definition like in the following sample:

private string _name;

public string Name
{
    get
    {
        return _name;
    }

    set
    {
        Set(ref _name, value);
        SayHello.RaiseCanExecuteChanged();
    }
}

Other than just using the Set() method to store the property and to send the notification to the user interface, we invoke the RaiseCanExecuteChanged() method of the SayHello command. This way, the boolean condition will be evaluated again: if the Name property contains some text, than the command will be enabled; otherwise, if it should become empty again, the command will be disabled.

In the next post

In this post we’ve finally started to apply with a real project the concepts we’ve learned in the first post and we have started to write our first application based on the MVVM pattern. In the next posts we’ll see some advanced scenario, like dependency injection, messages or how to handle secondary events. Meanwhile, you can play with the sample app we’ve created in this post, which is published on my GitHub repository https://github.com/qmatteoq/UWP-MVVMSamples. Together with the sample created in this post, you will find also the same sample created using Caliburn Micro as MVVM framework instead of MVVM Light. Happy coding!

Introduction to MVVM – The series

  1. Introduction
  2. The practice
  3. Dependency Injection
  4. Advanced scenarios
  5. Services, helpers and templates
  6. Design time data
Posted in Universal Apps, UWP, wpdev | Tagged , , | Leave a comment

The MVVM pattern – Introduction

Model-View-ViewModel (from now on, just MVVM) is a “love and hate” topic when it comes to Universal Windows app development. If you have never used it and you try it for the first time, you’ll probably find yourself a little bit confused, since it’s a completely different approach than the standard one based on the code behind. On the other side, if you’re a long time MVVM user, probably you won’t be able anymore to create a new project using any other approach. This is the reason why I’ve decided to write the following series of posts: what’s MVVM? Why is it so widely adpoted when it comes to Universal Windows apps development and, generally speaking, by any XAML based technology? I hope that, at the end of the journey, you’ll find an answer to all your questions and you’ll be able to start using the MVVM pattern in your apps without being scared anymore Smile

The MVVM pattern

The first thing you have to understand is that MVVM isn’t a framework or a library, but a pattern: it isn’t a set of APIs or methods, but a way to define the architecture of an application. Probably you’ve already heard about MVVM LIght or Caliburn Micro, but you don’t have to confuse them with MVVM: they’re tools that helps developers to adopt the MVVM pattern, they don’t represent the pattern itself.

The purpose of a pattern is to help developers to define the architecture of an application. Why is so important to do it? Why we cant’t simply continue to develop an application in the way we are used to, which is writing all the code in the code-behind class? The standard approach is very quick and simple to understand but it has many limitations when it comes to more complex projects, that needs to be maintained over time. The reason is that the code-behind class has a very tight dependency with the XAML page. Consequently, most of the code can’t be isolated and we end up to mix business logic and the presentation layer.

In the long run, the code behind approach introduces many problems:

  1. It’s more complicated to maintain the code and evolve the project. Every time we need to add a new feature or solve a bug, it’s hard to understand where precisely we need to it, since there isn’t a clear distinction between the various components of the app. This becomes even more true if we need to resume working on a project which has been “on hold” for a long time.
  2. It’s complex to perform unit testing. When it comes to complex projects, many developers and companies are adopting the unit test approach, which is a way to perform automatic tests that validate small pieces of code. This way it becomes easier to evolve the project: every time we add a new feature or we change some existing code, we can easily verify if the work we’ve done has broken the already existing features of the app. However, having a tight dependency between the logic and the user interface makes nearly impossible to write unit tests, since the code isn’t isolated.
  3. It’s complex to design the user interface: since there’s a tight relationship between the user interface and the business logic, it isn’t possible for a designer to focus on the user interface without knowing all the implementation details behind it. Questions like “where the data is coming from? A database? A cloud service?” shouldn’t be asked by a designer.

The goal of the MVVM pattern is to “break” this strong connection between the code behind and the user interface, making easier for a developer to understand which are the different components of the application. More precisely, it’s fundamental to distinguish the components which take care of the business logic and the ones that handle the data presentation.

The name of the pattern comes from the fact that the project is split into three different components, which now we’re going to explore in details.

The model

The model is the component of the application that defines and handles all the basic entities of the application. The goal of this layer is to remove any dependency from the way the data is represented. Ideally, you should be able to take the classes that belong to this component and use them in another application without applying any change. For example, if you’re working on an application to handle orders and customers of a company, the model could be defined by all the classes which define the base entities, like a customer, an order, a product, etc.

The view

The view is at the opposite side of the model and it’s represented by the user inteface. In the Universal Windows apps world, views are made by the XAML pages, which contain all the controls and animations that define the visual layout of the application. Recyicling the already mentioned sample of an app to handle orders and customers, we can have multiple views to display the list of customers, the available products in the warehouse, the orders made by a customer, etc.

The ViewModel

The ViewModel is the connection point between the view and model: it takes care of retrieving the raw data from the model and to manipulate it so that it can be properly displayed by the view. The huge difference with a code behind class is that the ViewModel is just a plain simple class, without any dependency from the View. In an application based on the MVVM pattern, typically you create a ViewModel for every View.

Why the MVVM pattern?

After this brief introduction, it should be easier to understand why the MVVM pattern is so important and how, by adopting it, we can solve all the problems mentioned at the beginning of the post.

  1. By splitting the code in three different layers it becomes easier, especially if you’re working in a team, to maintain and evolve the application. If you need to add a feature or to solve a bug, it’s easier to identify which layer has to be manipulated. Moreover, since there is no dependency between each layer, the work can be also done in parallel (for example, a designer can start working on the user interface while another developer can create the services which will be used by the page to retrieve the data).
  2. To properly perform unit testing, the code to test has to be as simple and isolated as possible. When you work with the code-behind approach, this is simply not possible: often the logic is connected to an event handler (for example, because the code has to be executed when you press a button) and you would need to find a way to simulate the event in order to trigger the code to test. By adopting the MVVM pattern we break this tight dependency: the code included in a ViewModel can be easily isolated and tested.
  3. Since we have broken the tight connection between the user interface and the business logic, for a designer it’s easy to define the interface without having to know all the implementation details of the application. For example, if the designer has to work on a new page which displays a list of orders, we can easily swap the real ViewModel (which retrieves the data from a real data source, like a cloud service or a database) with a fake one, which can generate fake data that allows to the designer to easily understand which kind of information the page should display.

Why in the Universal Windows app world most of the developers tend to use the MVVM pattern and not other popular patterns like MVC or MVP? Mainly, because the MVVM pattern is based on many features which are at the core of the XAML runtime, like binding, dependency properties, etc. In this series of post we’re going to talk a bit more about these features. You can notice how I’ve just mentioned XAML runtime and not the Universal Windows Platform: the reason is that most of the things we’re going to see in these posts aren’t specific of the Universal Windows app world, but they can be applied to any XAML based technology, like WPF, Silverlight, Windows Phone, Xamarin, etc.

Let’s see now, in details, which are the basic XAML features leveraged by the MVVM pattern.

The binding

Binding is one of the most important XAML features and allows to create a communication channel between two different properties. They can be properties that belong to different XAML controls, or a property declared in code with a control’s property. The key feature leveraged by the MVVM pattern is the second one: View and ViewModels are connected thanks to binding. The ViewModel takes care of exposing the data to show in the View as properties, which will be connected to the controls that will display them using binding. Let’s say, for example, that we have a page in the application that displays a list of products. The ViewModel will take care of retrieving this information (for example, from a local database) and to store it into a specific property (like a collection of type List<Order>):

public List<Order> Orders { get; set; }

To display the collection in a traditional code behind app, at some point, you would manually assign this property to the ItemsSource property of a control like ListView or GridView, like in the following sample:

MyList.ItemsSource = Orders;

However, this code creates a tight connection between the logic and the UI: since we’re accessing to the ItemsSource property using the name of the control, we can perform this operation only in the code behind class.

With the MVVM pattern, instead, we connect properties in the ViewModel with controls in the UI using binding, like in the following sample:

<ListView ItemsSource="{Binding Path=Orders}" /> 

This way, we have broken the dependency between the user interface and the logic, since the Orders property can be defined also in a plain simple class like a ViewModel.

As already mentioned, binding can be also bidirectional: this approach is used when not just the ViewModel needs to display some data in the View, but also the View should be able to change the value of one of the ViewModel’s properties. Let’s say that your application has a page where he can create a new order and, consequently, it includes a TextBox control where to set the name of the product. This information needs to be handled by the ViewModel, since it will take care of interacting with the model and adding the order to the database. In this case, we apply to the binding the Mode attribute and we set it to TwoWay, so that everytime the user adds some text to the TextBox control, the connected property in the ViewModel will get the inserted value.

If, in the XAML, we have the following code, for example:

<TextBox Text="{Binding Path=ProductName, Mode=TwoWay}" /> 

it means that in the ViewModel we will have a property called ProductName, which will hold the text inserted by the user in the box.

The DataContext

In the previous section we’ve seen how, thanks to the binding, we are able to connect the ViewModel’s properties to the controls in the XAML page. You may be wondering how the View model is able to understand which is the ViewModel that populates its data. To understand it, we need to introduce the DataContext’s concept, which is a property offered by any XAML Control. The DataContext property defines the binding context: every time we set a class as a control’s DataContext, we are able to access to all its public properties. Moreover, the DataContext is hierarchical: properties can be accessed not only by the control itself, but also all the children controls will be able to access to them.

The core of the implementation of the MVVM pattern relies on this hierarachy: the class that we create as ViewModel of a View is defined as DataContext of the entire page. Consequently, every control we place in the XAML page will be able to access to the ViewModel’s properties and show or handle the various information. In an application developed with the MVVM pattern, usually, you end up to have a page declaration like the following one:

<Page x:Class="Sample.MainPage" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      DataContext="{Binding Source={StaticResource MainViewModel}}" 
      mc:Ignorable="d"> 

    <!-- page content goes here -->

</Page> 

The DataContext property of the Page class has been connected to a new instance of the MainViewModel class.

The INotifyPropertyChanged interface

If we try to create a simple application based on the MVVM pattern applying the concepts we’ve learned so far, we would quickly hit a big issue. Let’s use the previous sample of the page to add a new order and let’s say that we have, in the ViewModel, a property which we use to display the product’s name, like the following one:

public string ProductName { get; set; } 

According to what we have just learned, we expect to have a TextBlock control in the page to display the value of this property, like in the following sample:

<TextBlock Text="{Binding Path=ProductName}" /> 

Now let’s say that, during the excecution of the app, the value of the ProductName proeprty changes (for example, because a data loading operation is terminated). We will notice how, despite the fact that the ViewModel will properly hold the new value of the property, the TextBlock control will continue to show the old one. The reason is that binding isn’t enough to handle the connection between the View and the ViewModel. Binding has created a channel between the ProductName property and the TextBlock, but no one notified both sides of the channel that the value of the property has changed. For this purpose, XAML offers the concept of dependency properties, which are special properties that can define a complex behavior and, under the hood, are able to send a notification to both sides of the binding channel every time its value changes. Most of the basic XAML controls use dependency properties (for example, the Text property of the TextBlock control is a dependency property). However, defining a new dependency property isn’t very straightforward and, in most of the cases, it offers features which aren’t needed for our MVVM scenario. Let’s take the previous sample based on the ProductName property: we don’t need to handle any special behavior or logic, we just need that, every time the ProductName property changes, both sides of the binding channel receive a notification, so that the TextBlock control can update its visual layout to display the new value.

For these scenarios, XAML offers a specific interface called INotifyPropertyChanged, which we can implement in our ViewModels. This way, if we need to notify the UI when we change the value of a property, we don’t need to create a complex dependency property, but we just need to implement this interface and invoke the related method every time the value of the property changes.

Here is how a ViewModel that implements this interface looks like:

public class MainViewModel: INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    [NotifyPropertyChangedInvocator] 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

You can notice how the implementation of this interface allows us to call a method called OnPropertyChanged(), that we can invoke every time the value of a property changes. However, to reach this goal, we need to change the way how we define the properties inside our ViewModel. When it comes to simple properties, usually we define them using the short syntax:

public string ProductName { get; set; } 

Hower, with this syntax we can’t change what happens when the value of the property is written or read. As such, we need to go back to use the old approach, based on a private variable which holds the value of the property. This way, when the value is written, we are able to invoke the OnPropertyChanged() method and dispatch the notification. Here is how a property in a ViewModel looks like:

private string _productName; 

public string ProductName 
{ 
    get { return _productName; } 
    set 
    { 
        _productName = value; 
        OnPropertyChanged(); 
    } 
} 

Now the property will work as expected: when we change its value, the TextBlock control in binding with it will change his appearance to display it.

Commands (or how to handle events in MVVM)

Another critical scenario when it comes to develop an application is to handle the interactions with the user: he could press a button, choose an item in a list, etc. In XAML, these scenarios are handled using events which are exposed by various controls. For example, if you want to handle that the button has been pressed, we need to subscribe to the Click event, like in the following sample:

<Button Content="Click me" Click="OnButtonClicked" /> 

The event is managed by an event handler, which is a method that includes, among the various parameters, some information which are useful to understand the event context (for example, the control which triggered the event or which item of the list has been selected), like in the following sample:

private void OnButtonClicked(object sender, RoutedEventArgs e) 
{ 
    //do something 
} 

The problem of this approach is that event handlers have a tight dependency with the View: they can be declared, in fact, only in the code behind class. When you create an application using the MVVM pattern, instead, all the data and logic is usually defined in the ViewModel, so we need to find a way to handle the user interaction there.

For this purpose, the XAML has introduced commands, which is a way to express a user interaction with a property instead that with an event handler. Since it’s just a simple property, we can break the tight connection between the view and the event handler and we can define it also in an independent class, like a ViewModel.

The framework offers the ICommand interface to implement commands: with the standard approach, you end up having a separated class for each command. The following example shows how a command looks like:

public class ClickCommand : ICommand 
{ 
    public bool CanExecute(object parameter) 
    { 
    } 

    public void Execute(object parameter) 
    { 
    } 

    public event EventHandler CanExecuteChanged; 

} 

The core of the command is the Execute() method, which contains the code that is executed when the command is invoked (for example, because the user has pressed a button). It’s the code that, in a traditional application, we would have written inside the event handler.

The CanExecute() method is one of the most interesting features provided by commands, since it can be used to handle the command’s lifecycle when the app is running. For example, let’s say that you have a page with a form to fill, with a button at the end of the page that the user has to press to send the form. Since all the fields are required, we want to disable the button until all the fields have been filled. If we handle the operation to send the form with a command, we are able to implement the CanExecute() method in a way that it will return false when there’s at least one field still empty. This way, the Button control that we have linked to the command will automatically change his visual status: it will be disabled and the user will immediately understand that he won’t be able to press it.

clip_image002

In the end, the command offers an event called CanExecuteChanged, which we can invoke inside the ViewModel every time the condition we want to monitor to handle the status of the command changes. For example, in the previous sample, we would call the CanExecuteChanged event every time the user fills one of the fields of the form.

Once we have define a command, we can link it to the XAML thanks to the Command property, which is exposed by every control that are able to handle the interaction with the user (like Button, RadioButton, etc.)

<Button Content="Click me" Command="{Binding Path=ClickCommand}" /> 

As we’re going to see in the next post, however, most of the toolkits and frameworks to implement the MVVM pattern offers an easier way to define a command, without forcing the developer to create a new class for each command of the application. For example, the popular MVVM Light toolkit offers a class called RelayCommand, which can be used to define a command in the following way:

private RelayCommand _sayHello; 

public RelayCommand SayHello 
{ 
    get 
    { 
        if (_sayHello == null) 
        { 
            _sayHello = new RelayCommand(() => 
            { 
                Message = string.Format("Hello {0}", Name); 
            }, () => !string.IsNullOrEmpty(Name)); 
        } 

        return _sayHello; 
    } 
} 

As you can see, we don’t need to define a new class for each command but, by using anonymous methods, we can simply create a new RelayCommand object and pass, as parameters:

  1. The code that we want to excecute when the command is invoked.
  2. The code that evaluates if the command is enabled or not.

We’re going to learn more about this approach in the next post.

How to implement the MVVM pattern: toolkits and frameworks

As I’ve mentioned at the beginning of the post, MVVM is a pattern, it isn’t a library or a framework. However, as we’ve learned up to now, when you create an application based on this pattern you need to leverage a set of standard procedures: implementing the INotifyPropertyChanged interface, handling commands, etc.

Consequently, many developers have started to work on libraries that can help the developer’s job, allowing them to focus on the development of the app itself, rather than on how to implement the pattern. Let’s see which are the most popular libraries.

MVVM Light

MVVM Light (http://www.mvvmlight.net) is a library created by Laurent Bugnion, a long time MVP and one of the most popular developers in the Microsoft world. This library is very popular thanks to its flexibility and simplicity. MVVM Light, in fact, offers just the basic tools to implement the pattern, like:

  • A base class, which the ViewModel can inherit from, to get quick access to some basic features like notifications.
  • A base class to handle commands.
  • A basic messaging system, to handle the communication between different classes (like two ViewModels).
  • A basic system to handle dependency injection, which is an alternative way to initialize ViewModels and handle their dependencies. We’ll learn more about this concept in another post.

Since MVVM Light is very basic, it can be leveraged not just by Universal Windows apps, but also in WPF, Sivlerlight and even Android and iOS thanks to its compatibility with Xamarin. Since it’s extremely flexible, it’s also easy to adapt it to your requirements and as a starting point for the customization you may want to create. This simplicity, however, is also the weakness of MVVM Light. As we’re going to see in the next posts, when you create a Universal Windows app using the MVVM pattern you will face many challenges, since many basic concepts and features of the platform (like the navigation between different pages) can be handled only in a code behind class. From this point of view, MVVM Light doesn’t help the developer that much: since it offers just the basic tools to implement the pattern, every thing else is up to the developer. For this reasons, you’ll find on the web many additional libraries (like the Cimbalino Toolkit) which extend MVVM Light and add a set of services and features that are useful when it comes to develop a Universal Windows app.

Caliburn Micro

Caliburn Micro (http://caliburnmicro.com) is a framework originally created by Rob Eisenberg and now maintained by Nigel Sampson and Thomas Ibel. If MVVM Light is a toolkit, Caliburn Micro is a complete framework, which offers a completely differnent approach. Compared to MVVM Light, in fact, Caliburn Micro offers a rich set of services and features which are specific to solve some of the challenges provided by the Universal Windows Platform, like navigation, storage, contracts, etc.

Caliburn Micro handles most of the basic features of the pattern with naming conventions: the implementation of binding, commands and others concepts are hidden by a set of rules, based on the names that we need to assign to the various components of the project. For example, if we want to connect a ViewModel’s property with a XAML control, we don’t have to manually define a binding: we can simply give to the control the same name of the property and Caliburn Micro will apply the binding for us. This is made possible by a boostrapper, which is a special class that replaces the standard App class and takes care of intializing, other than the app itself, the Caliburn infrastructure.

Caliburn Micro is, without any doubt, very powerful, since you’ll have immediate access to all the tools required to properly develop a Universl Windows app using the MVVM pattern. However, in my opinion, isn’t the best choice if you’re new to the MVVM pattern: since it hides most of the basic concepts which are at the core of the pattern, it can be complex for a new developer to understand what’s going on and how the different pieces of the app are connecte together.

Prism

Prism (http://github.com/PrismLibrary/Prism) is another popular framework which, in the beginning, was created and maintaned by the Pattern & Practises division by Microsoft. Now, instead, it has become a community project, maintained by a group of independent developers and Microsoft MVPs.

Prism is a framework and uses a similar approach to the one provided by Caliburn Micro: it offers naming convention, to connect the different pieces of the app together, and it includes a rich set of services to solve the challenges provded by the Universal Windows Platform.

We can say that it sits in the middle between MVVM Light and Caliburn Micro, when it comes to complexity: it isn’t simple and flexible like MVVM Light but, at the same time, it doesn’t use naming convention in an aggressive way like Caliburn Micro does.

Coming soon

In the next posts we’re going to turn what we’ve learned so far int oa realy project and we’re going to leverage MVVM Light for this purpose: the reason is that, as I’ve already mentioned, I think MVVM Light is the easiest one to understand, especially if you’re new to the pattern, since it will help us to learn all the basic concepts which are at the core of the pattern. If you want to start looking at a real project, you’ll find many samples (which we’re going to explain in a more detailed way) on my GitHub repository at https://github.com/qmatteoq/UWP-MVVMSamples. Stay tuned!

P.S.= this post has been written with OpenLiveWriter, the new open source version of Windows Live Writer, which has now become a community driven project. In my opinion (and not just mine Smile) Open Live Writer is the best tool in the world to write blog posts, so thanks to Microsoft for making this happen and thanks to all the great developers that are contributing to the project and keeping it alive!

Introduction to MVVM – The series

  1. Introduction
  2. The practice
  3. Dependency Injection
  4. Advanced scenarios
  5. Services, helpers and templates
  6. Design time data
Posted in Universal Apps, UWP, wpdev | Tagged , | 1 Comment

Template10: a new template to create Universal Windows apps – MVVM

The Model-View-ViewModel pattern (from now on, just MVVM) is, without any doubt, the most widely used pattern when it comes to develop XAML based applications. In this post, we won’t learn all the inner details of the pattern: I’ve already talked about it many times in this blog, when I presented some of the most popular MVVM frameworks like Caliburn Micro and Prism.  The goal of the MVVM pattern is to improve testability and maintainability of an application, since it helps the developer in reaching one of the key goals that drives any complex development project: keeping the different layers separated, so that the code that handles the user interface doesn’t mix with the one that handles the business logic (like retrieving the data from the cloud or from a database).

The MVVM pattern is heavily used in the Universal Windows app world and, generally speaking, also in all the XAML based technologies, since it relies on the basic XAML feature like binding, dependency properties, the INotifyPropertyChanged interface, etc. When you use this pattern, you typically split the project into three components:

  1. The model, which are the entities and the services that are used to handle the raw data of the application, without dependencies on how they are presented.
  2. The view, which is the user interface presented to the user. In Universal Windows apps, the Views are identified with the XAML pages.
  3. The ViewModel, which is the connection between the view and the model. ViewModel are simple classes that takes care of retrieving the data handled by the model and of preparing them to be presented by the View using binding.

The MVVM pattern gives to developers a lot of benefits but, however, it requires some time to be configured into a new project: the problem is that when you create a new Universal Windows app there are a lot of scenarios (navigation, the application’s lifecycle, contracts, etc.) which are simple to implement when you use code-behind, but that need to be reviewed when you use the MVVM pattern, since most of the code is written in a ViewModel, which is an independent class. A good example of this problem is the page lifecycle management: typically, in a Universal Windows app you use the OnNavigatedTo() and OnNavigatedFrom() events to handle the navigation from one page to another. However, these events are exposed only by the code behind class, since it inherits from the Page class; you can’t use them in a ViewModel, which doesn’t have any dependency from it.

For this reason, many developers have created libraries and frameworks which makes the developer’s life easier, by providing all the needed tools. The most popular ones are MVVM Light by Laurent Bugnion, Caliburn Micro by Rob Esieneberg and Prism, originally developed by the Microsoft Pattern & Practice division and now turned in to a community project. Every framework has its own pros and cons: MVVM Light is the simplest and most flexible one, but it lacks any helper to handle the typical scenarios of a Universal Windows app. Caliburn Micro and Prism, on the other side, are more complex to master and a little bit “rigid”, but they offer many tools to handle common scenarios like navigation, page lifecycle, etc.

Template10 doesn’t act as another MVVM framework (even if, as we’re going to see, it offers some classes to implement it without having to rely on another library), but it helps developers to make the implementation of the MVVM pattern easier. Let’s see in details which are these facilities: it’s important to remember that what we have described in the previous posts (bootstrapper, extended splash screen, the new controls, etc.) can be applied also on MVVM based projects.

The basic tools to implement the pattern

Even if Template10 doesn’t behave as a complete alternative to the existing libraries, it offers any way the basic tools required to implement it in the proper way. You aren’t forced to use them: you can choose, for example, to add MVVM Light to your project and to use its helpers in replacement of the ones that I’m going to describe.

The first important helper offered by Template10 is the ViewModelBase class, which is the base class which your ViewModels should inherit from. Other than offering a set of useful features that we’re going to see later in this post, it offers the basic tools to implement the pattern. The most important one is the Set() method, which can be used to propagate the changes to the ViewModel properties to the user interface, by implementing the INotifyPropertyChanged interface. Here is how you can use it to define a property in the ViewModel:

public class MainViewModel : Template10.Mvvm.ViewModelBase 
{ 
    public MainViewModel() 
    { 

    } 

    private string _name; 

    public string Name 

    { 
        get { return _name; } 
        set { Set(ref _name, value); } 
    } 
} 

The Set() method, invoked inside the property’s setter, allows to send a notification to the view that the value has changed, other than just effectively changing the value of the property. This way, if in the View you have one or more controls connected to this property through binding, they will update their visual state to reflect the changes. For example, here is how you can connect a TextBlock control placed in the XAML page to the property we’ve just declared:

<TextBlock Text="{Binding Path=Name}" /> 

If you already have some experience with MVVM Light, this approach will be familiar to you: also this toolkit offers a method called Set(), which has the same purpose.

Another important feature that Template10 implements is the DelegateCommand class, which can be used to easily create commands. Which is the purpose of commands? When it comes to handle the user interaction in a traditional application created using the code-behind approach, you rely on event handlers: they’re methods that are connected to an event that is raised by a control, like pressing a button or selecting an item from a list. These event handlers have a tight dependency with the view and, as such, they can be declared only in the code-behind class. In a MVVM application, instead, most of the logic is handled by the ViewModel and, consequently, we would need to handle the user interaction in a ViewModel. This is exactly the purpose of commands: a way to handle an event using a property, so that we can connect it to a control using binding. This way, we can “break” the dependency that traditional event handlers have with the view and we can declare commands in any class, including ViewModels.

A command is defined by:

  1. The actions to perform when the command is invoked.
  2. The condition that needs to be satisfied to enable the command. This feature is very useful, because it makes sure that the control connected to the command automatically changes his visual status based on the command status. For example, if a command is connected to a Button control and, during the execution, the command is disabled, also the button will be disabled: it will be displayed in grey and the user won’t be able to tap on it.

The Windows Runtime offers a base class to implements commands, called ICommand: however, it’s just an interface, the concrete implementation is up to the developer, who would need to create a class for every command. To reduce the footprint and speed up the development, Template10 offers a class called DelegateCommand, which implements this interface and that can be initialized simply by passing to the constructor the two required information. Here is an example:

private DelegateCommand _setNameCommand; 

public DelegateCommand SetNameCommand 
{ 
    get 
    { 
        if (_setNameCommand == null) 
        { 
            _setNameCommand = new DelegateCommand(() => 
            { 
                Result = $"Hello {Name}"; 
            }, () => !string.IsNullOrEmpty(Name)); 

        } 

        return _setNameCommand; 

    } 
} 

The first parameter is an Action (in this case, it’s defined using an anonymous method), which defines the operations to execute when the command is invoked. The second optional parameter, instead, is a function that should return a boolean value and that is used to determine if the command is enabled or not. In the sample, the command is enabled only in case the content of the Name property isn’t empty.

Once you have defined a command, you can connect it to a XAML control using the property with the same name, which is exposed by all the controls that support the user interaction (like the Button control).  The following sample shows how to use the Command property offered by the Button control to connect the DelegateCommand property we’ve previously defined.

<Button Content="Click me" Command="{Binding Path=SetNameCommand}" /> 

Also in this case, if you have previous experience with MVVM Light, the approach will be familiar: the toolkit, in fact, offers a class called RelayCommand for the same purpose and which works in the same way.

Navigation and page’s lifecycle

We already mentioned this scenario multiple times in this post: one of the key scenarios to handle in a Universal Windows app is the page’s lifecycle. Frequently, the navigation events are used to handle basic operations like data loading. As such, having access to these kind of events also in a ViewModel is critical, since usually all the logic is there.

For this purpose, the ViewModelBase class offers a set of additional features to make the developer’s life easier. The first feature is the implementation of an interface called INavigable, which allows to access to the navigation events directly in a ViewModel, like in the following sample:

public class DetailViewModel : ViewModelBase 
{ 
    public override void OnNavigatedTo(object parameter, NavigationMode mode, IDictionary<string, object> state) 
    { 
        if (parameter != null) 
        { 
            int id = (int) parameter; 
            //load data 
        } 
    } 

    public override Task OnNavigatedFromAsync(IDictionary<string, object> state, bool suspending) 
    { 
        return base.OnNavigatedFromAsync(state, suspending); 
    } 
} 

As you can see, thanks to this base class you get a 1:1 mapping with the same methods that are available in the code-behind class. You get also useful information about the navigation, like parameters that have been passed from another page or the NavigationMode, which can be useful to distinguish the different navigation scenarios (for example, you may decide to load the application’s data only when the NavigationMode parameter is set to New, which means that it’s a new navigation).

Another navigation feature offered by the ViewModelBase class is the NavigationService, which is a helper that can be used to trigger the navigation from one page to another directly in the ViewModel. Again, this is a scenario that, without this helper, would be supported only in the code-behind class: navigation is handled, in fact, by the Frame class, which can be accessed only in code-behind. The NavigationService class is pretty straightforward to use, since it mimics the behavior of the Frame one: to navigate from one page to another you can use the Navigate() method, passing as information the page’s type and, optionally, a parameter.

NavigationService.Navigate(typeof(DetailPage), person?.Id); 

As you can see in the documentation, the Navigate() method accepts as parameter a generic object: however, it isn’t a good practice to pass complex objects from one page to another, but it’s better to stick with simple types (a string, a number, etc.). This way, we make sure not to break the state management system implemented by Template10 (that we’re going to see later), which requires that parameters needs to be serializable.

Handle the page’s state

One of the most important scenarios to handle in a Universal Windows app is the application’s lifecycle. When an application isn’t in foreground anymore, it’s suspended: the process is frozen in memory (so that the state is preserved) but all the threads that can use CPU, battery or network are terminated. When the application is resumed, we don’t have to do anything special: since the state was preserved in memory, the app will be restored exactly as it was. However, the operating system can decide to terminate a suspended application in case the resources are running low. In this case, since the process is completely killed, when the app is resumed it won’t automatically be restored to the previous state. As developers, we need to handle this scenario: since the termination by the OS is completely transparent to the user, he will expect to find the application as he left it. It’s our duty to properly save and restore the page’s state. Let’s say, for example, that our application includes a page with some fields that the user needs to fill before moving on (like a registration form). Once the application is suspended and then resumed, he would expect to find the data he already filled already there and not to fill the entire form from scratch.

When you use the MVVM pattern, handling this scenario introduces some challenges:

  1. Since we don’t know for sure if the suspended application will be terminated or not, we need to save the page’s state every time a new navigation is performed. When you use the MVVM pattern without relying on other libraries (like Template10), this requirement is hard to handle because we don’t have access to the navigation events in a ViewModel.
  2. When the application is suspended, we need to save in the local storage the application’s state, like the content of the registration form or the last visited page. Then, when the application is resumed, we need to understand if it was terminated and, consequently, restore the state we’ve previously saved. Unfortunately, the basic Windows 10 template doesn’t offer any tool or API to make easier for the developer to support this scenario.

Template10 makes the whole process a lot easier. When we have seen the sample code about handling the page’s lifecycle, you may have noticed that the OnNavigatedTo() and OnNavigatedFrom() events expose a parameter called state. It’s a dictionary, which can contain a list of key-value pairs, that are automatically serialized and deserialized in the local storage when the app is suspended or resumed. When the application is suspended, you’re going to use the OnNavigatedFrom() method to add in the dictionary all the information we need to recover the application’s state. When the page is loaded, instead, in the OnNavigatedTo() event, we’ll retrieve the previously saved info and we’ll assign them to the proper properties in the ViewModel.

Let’s see a real sample, by defining a page with a TextBox control. The user can insert any text in it, which is saved into a ViewModel property, like the following one

private string _name; 

public string Name 
{ 

    get { return _name; } 
    set { Set(ref _name, value); } 
} 

The property is connected, as usual, to the TextBox control using binding:

<TextBlock Text="{Binding Path=Name, Mode=TwoWay}" /> 

You can notice that the binding has been configured using the TwoWay mode: this way, every time the user will write something in the TextBox, the Name property in the ViewModel will be automatically updated with the new value.

Now you can try to suspend the application and to open it back, by using the dropdown menu called Lifecycle events in Visual Studio, that allows to simulate the different stages of the application’s lifecycle. It’s important to remind, in fact, that when the debugger is attached, the app is not suspended when you put in background, like instead happens during the regular usage. If we write some text in the TextBox control, then we suspend the app and we open it back, we will find everything as we’ve left, since the app was just suspended and the process kept in memory. However, if we try to do the same but using the Suspend and shutdown option, you will notice that the content of the TextBox control will be gone: the process has been indeed terminated and, since we didn’t save the content of the TextBox, the data was lost during the restore process.

clip_image002

To avoid this issue we can use the dictionary I’ve previously mentioned: in the OnNavigatedFrom() method of the ViewModel we can understand if the app is being suspended and, eventually, save in the collection the information we need to restore the state.

public class DetailViewModel : ViewModelBase 
{ 

    private string _name; 

    public string Name 
    { 
        get { return _name; } 
        set { Set(ref _name, value); } 
    } 

    public override Task OnNavigatedFromAsync(IDictionary<string, object> state, bool suspending) 
    { 
        if (suspending) 
        { 
            state.Add("Name", Name); 
        } 
        
        return base.OnNavigatedFromAsync(state, suspending); 
    } 
} 

By using the boolean parameter called suspending we understand if the app is being suspended: if that’s the case, we can save into the dictionary called state the value of the Name property, by matching it to a key with the same name. This way, during the suspension, Template10 will automatically take care of serializing the content of this dictionary into the local storage in a text file. Now it will be easier for you to understand one of the key requirements of this implementation: we can store into the dictionary only simple data, that can be serialized into XML or JSON file. Saving, for example, an image stream into the dictionary wouldn’t work.

The next step is to handle the page loading: in case the state dictionary contains some data in the OnNavigatedTo() method, then it means that the app is being resumed from a suspension and we need to retrieve the. Also in this case most of the work will be done by Template10: the bootstrapper will take care of loading the data that was previously serialized and it will automatically redirect the user to the last visited page of the application. This way, we can simply access to the state parameter in the OnNavigatedTo() method and use the data to populate back the properties in our ViewModel, like in the following sample:

public class DetailViewModel : ViewModelBase 
{ 

    private string _name; 

    public string Name 
    { 
        get { return _name; } 
        set { Set(ref _name, value); } 
    } 

    public override void OnNavigatedTo(object parameter, NavigationMode mode, IDictionary<string, object> state) 
    { 
        if (state.Any()) 
        { 
            Name = state["Name"].ToString(); 
            state.Clear(); 
        } 

    } 

    public override Task OnNavigatedFromAsync(IDictionary<string, object> state, bool suspending) 
    { 
        if (suspending) 
        { 
            state.Add("Name", Name); 
        } 

        return base.OnNavigatedFromAsync(state, suspending); 
    } 
} 

Inside the OnNavigatedTo() method we check if there is any data inside the dictionary: only in this case we retrieve the value identified by the Name key and we assign it to the proper ViewModel’s property. The next step is to clear the content of the collection (using the Clear() method), to avoid that the data is retrieved again also when we’re simply navigating from one page to another.

Now we can try again to suspend the app using the Suspend and shutdown option offered by Visual Studio: now the application will behave as expected and the content of the TextBox control will still be there.

Important! It’s crucial to remind that this approach has to be used to save the page’s state, not the application data. Data generated by the user has to be saved as soon as possible, to minimize data loss in case of unexpected errors. During the suspension, you have between 5 and 10 seconds to complete all the pending operations, which may not be enough to save all the data handled by your application. The only data we need to save during suspension are the one that makes easier for the developer to create the illusion that the app has never been closed, even if it was silently terminated by the operating system.

Access to the UI thread

Sometimes you may have the requirement, inside a ViewModel, to perform some operations on background threads. In this case, if we try to directly access to one of the UI controls (for example, because we need to change the value of a property which is connected to a control in the View), we ill get an exception: the reason is that we’re trying to access to the UI thread from a secondary one.

The Windows Runtime offers a class called Dispatcher to solve this problem: it’s a sort of “mailman”, which is able to dispatch some operations to the UI thread, regardless of the thread where the execution is happening. Also in this case, we’re talking about a class which can be easily accessed from a code-behind class, but the same doesn’t apply to an independent class like a ViewModel. Template10 includes a helper that makes easier to access to the dispatcher also from a third party class, like a ViewModel, by exposing a property called Dispatcher as part of the ViewModelBase infrastructure:

await Dispatcher.DispatchAsync(() => 
{ 
    //do something on the UI thread 
}); 

Using it is very easy: just call the DispatchAsync() method of the Dispatcher class by passing, as parameter, an Action with the operations that you want to perform on the UI thread.

Wrapping up

Template10 can be really helpful when you’re working with the MVVM pattern in a Universal Windows app: you can focus on getting things done, rather than trying to reinvent the wheel every time to handle the fundamentals of Universal Windows app development. However, Template10 is still growing and the number of services that will make easier to integrate Windows features into a ViewModel will continue to grow!

For the moment, we’ve finished our journey to discover the Template10 features, but I’m sure we’ll have the chance to talk about it again in the future. Don’t forget that you can find all the information about the project, in addition to many samples, on the official GitHub repository https://github.com/Windows-XAML/Template10

Posted in Universal Apps, wpdev | Tagged , , | 5 Comments

Template10: a new template to create Universal Windows apps – The controls

In the previous post we started to know Template10, the new open source template developed by a Microsoft, with the goal to become the starting point for every Universal Windows app developer. In this post we’re going to see some cool custom controls provided by the library.

The PageHeader control

One of the new features available in Windows 10, when it comes to design the user interface, is the improved flexibility regarding the application bars. In Windows and Windows Phone 8.1 you were able to place an application bar only at the bottom of the screen. Only in Windows 8.1 you were allowed to have a top application bar, but not for commanding purposes: it had to be used to make easier for the user to navigate through the sections of the application.

The bottom application bar was implemented using a control called CommandBar, which makes easier for the developer to quickly add buttons so that that the user can interact with the content on the screen. Windows 10 allows, instead, to place the CommandBar control also at the top. The PageHeader control is an extension of the CommandBar one, so that you can use it not just to provide commands to the user, but also to act as a real header of the page. Thanks to this control, it will be easier to implement the same look & feel offered by many native applications like News or Money, which offer an header with the tile of the page and a set of buttons to handle navigation or content interaction.

The first step to add a PageHeader control is to declare in the XAML page the required namespace, which is Template10.Controls, like in the following sample:

<Page
    x:Class="Controls.Views.MainPage"
    xmlns:controls="using:Template10.Controls"
    mc:Ignorable="d">

    
</Page>

Now you can add the control to your page by using the following code:

<controls:PageHeader Frame="{x:Bind Frame}" />

One of the key properties is called Frame. As we’re going to se later, one of the key features provided by the control is the built-in management of the navigation framework. To make this feature working, we need to connect to the PageHeader control the application’s frame, which handles the pages and the navigation between them: we can do it using the new x:Bind markup extensions, which is able to perform a binding with objects exposed by the code behind class.

This is how the standard PageHeader control looks like:

 

clip_image002

Customizing the control

The key property to customize the PageHeader control is Text, which allows to set the text that is displayed in the header (typically, the title of the page). Eventually, you can also customize the standard color that is assigned to the text and to the background, by using the HeaderForeground and HeaderBackground properties. The following samples shows a customized header, with a red text and an orange background.

<controls:PageHeader Text="Main Page" Frame="{x:Bind Frame}" HeaderBackground="Orange" HeaderForeground="Red" />

clip_image004

Handle navigation

The PageHeader control offers a built-in back button to handle the navigation towards the previous page of the application, which is controlled by a property called BackButtonVisibility. When this property is set to Visible, the button is displayed at the left of the header’s text.

<controls:PageHeader Text="Detail" Frame="{x:Bind Frame}" BackButtonVisibility="Visible" />

clip_image006

However, it’s very important to highlight that the button’s visibility isn’t controlled just by this property, but also by the operating system, which can override our configuration. Specifically:

  1. The control, thanks to the Frame property, is connected to the navigation’s frame. Consequently, it’s able to automatically detect if there are pages in the back stack so that if it’s empty (for example, because you’re in the main page), the button will always be hidden.
  2. Windows 10 can run on multiple devices, which can offer a different navigation experience. If, on the desktop, we have more freedom (we can use the virtual back button embedded in the chrome or include it in the UI of the application), on mobile instead you need to leverage the hardware back button available on every device. As such, if you set the BackButtonVisibility property of the control to Visible but the app is running on a phone, the button will be hidden anyway.
  3. On desktop, as we’ve seen in the previous post, we have the chance to leverage a virtual back button, which is added on the app’s chrome, to handle the navigation. If we have enabled this option (which Template10 applies by default but that can be controlled by the ShowShellBackButton property of the BootStrapper class), the PageHeader control’s button will be hidden anyway.

The commands

As mentioned in the beginning of the post, PageHeader extens the CommandBar control, which is used to add an application bar with one or more commands, so that the user can interact with the current content. Consequently, the PageHeader control offers the same features of the CommandBar one and follows the same principles:

  • Inside the PrimaryCommands collection you can add one or more buttons, which will always be visible and represented by an icon and a label.
  • Inside the SecondaryCommands collection you can add one or more buttons which, instead, will be hidden by default: the user will be able to see them only by tapping on the three dots displayed at the end of the bar. Secondary commands are represented only with a label.

Inside the two collections you don’t have the freedom to add any XAML control, but there’s a specific subset of controls which has been designed to work with a CommandBar. The most used one is AppBarButton, which represents a button that the user can press. It can have an image (defined by the Icon property) and a description (defined by the Label property) and you can subscribe to the Click event to handle the user’s interaction.

The following sample code defines a PageHeader control with one primary command and two secondary commands:

<controls:PageHeader Text="Main Page" Frame="{x:Bind Frame}">
    <controls:PageHeader.PrimaryCommands>
        <AppBarButton Icon="Forward" Label="Next" Click="OnNextClicked" />
    </controls:PageHeader.PrimaryCommands>
    <controls:PageHeader.SecondaryCommands>
        <AppBarButton Label="Option 1" />
        <AppBarButton Label="Option 2" />
    </controls:PageHeader.SecondaryCommands>
</controls:PageHeader>

clip_image008

 

It’s really important to evaluate how many buttons you want to add in the control, especially if you’re application targets multiple families of devices. For example, the usage of many primary commands isn’t a big deal on the desktop: since the screen is bigger and usually in landscape, there’s plenty of available space. The same rules don’t apply to a smartphone: in this scenario, it’s better to reduce the number of primary commands and rely more on the secondary ones.

The following image shows the same layout with three primary commands: you can notice how it works perfectly on the desktop, but it messes up on the mobile (due to the reduced space, the buttons overlaps with the header’s text).

 

clip_image010

 

The HamburgerMenu control

Another new Windows 10 feature is the SplitView control, which can be used to implement navigation experiences based on the hamburger menu in your applications. This approach is based on a side panel (typically, it’s placed on the left of the screen) which the user can expand by tapping a button on the top of the panel (usually, in the top left corner). Inside the panel you can usually find multiple items, which can be used to quickly jump from one section to another of the application. The name comes from the fact that the button to show or hide the panel is visually represented by thee lines, one on top of the other, which look like a hamburger between two pieces of bread.

Many native applications are using this approach, like News (which uses the panel to give access to the different sections of the app) or Mail (which, instead, uses the panel to show the available mail accounts with their sub folders).

The SplitView control is just one of the many controls that are available to define the navigation experience of your application: it’s not the only one and Microsoft doesn’t want to force you to use it in any application you create. It’s up to the developer to find the navigation approach that works best for him. Consequently, the SplitView control leaves a lot of freedom to the developer. It just gives you an easy way to split the page in two parts: a sliding panel and the main content. It’s up to you to define the look & feel of both parts.

The downside of this freedom is that we have a bit of work to do if we want, instead, implement a traditional hamburger menu navigation, similar to the one used by some native apps. Template10 simplifies a lot our job since:

  1. It offers a control called HamburgerMenu, which makes easier to define the panel that will contain the list of application’s sections.
  2. It offers a way to create a shell, which is a special page that will act as a container for the application. The shell will contain the menu, while the content area will be filled with the various pages of the application.
  3. It offers a set of built-in styles to recreate a panel with the same look & feel of the one used by native apps (highlight of the current section, icon support, etc.)

Thanks to Template10 we’ll be able to achieve a result very close to the following one:

clip_image012

Let’s see how to implement it.

The HamburgerMenu control

Like the PageHeader control, the HamburgerMenu one is defined inside the Template10.Controls namespace, which you need to add in the XAML declaration. After that, you’ll be able to add it into a page:

<controls:HamburgerMenu x:Name="Menu" />

Customization is allowed thanks to the following properties:

  • HamburgerBackground and HamburgerForeground define the background and foreground color of the hamburger button (the one used to show / hide the panel)
  • NavButtonBackground and NavButtonForeground define the background and foreground color of the buttons in the panel.
  • NavAreaBackground defines the background color of the panel.

An important feature offered by the HamburgerMenu control, compared to the standard SplitView one, is built-in support to two categories of commands, similarly to the PageHeader control:

  • PrimaryButtons identifies the most used sections of the your application and they are placed at the top of the panel, right below the hamburger button.
  • SecondaryButtons identifies the sections of your app that the user will probably visit less frequently, like the Settings or the About page. They are displayed at the bottom of the panel, with a separator at the top.

Inside both collections you can leverage a specific control offered by Template10 called NavigationButtonInfo, which will recreate for you the look & feel of the buttons you can find in the native application. Under the hood, it’s based on the RadioButton control, since it already implements a set of features that are ideal for our scenario (mutual choice between each button, highlight of the currently selected item, etc.)

The following sample shows a complete definition of the HamburgerMenu control:

<controls:HamburgerMenu x:Name="Menu"
                        HamburgerBackground="#FFD13438"
                        HamburgerForeground="White"
                        NavAreaBackground="#FF2B2B2B"
                        NavButtonBackground="#FFD13438"
                        NavButtonForeground="White">

    <controls:HamburgerMenu.PrimaryButtons>
        <controls:NavigationButtonInfo PageType="views:MainPage" ClearHistory="True">
            <StackPanel Orientation="Horizontal">
                <SymbolIcon Symbol="Home" Width="48" Height="48" />
                <TextBlock Text="Home" Margin="12, 0, 0, 0" />
            </StackPanel>
        </controls:NavigationButtonInfo>
            
        <controls:NavigationButtonInfo PageType="views:DetailPage">
            <StackPanel Orientation="Horizontal">
                <SymbolIcon Symbol="Calendar" Width="48" Height="48" />
                <TextBlock Text="Calendar" Margin="12, 0, 0, 0" />
            </StackPanel>
        </controls:NavigationButtonInfo>
    </controls:HamburgerMenu.PrimaryButtons>
        
    <controls:HamburgerMenu.SecondaryButtons>
        <controls:NavigationButtonInfo PageType="views:SettingsPage">
            <StackPanel Orientation="Horizontal">
                <SymbolIcon Symbol="Setting"  Width="48" Height="48" />
                <TextBlock Text="Settings" Margin="12, 0, 0, 0" />
            </StackPanel>
        </controls:NavigationButtonInfo>
    </controls:HamburgerMenu.SecondaryButtons>
        
</controls:HamburgerMenu>

The samples shows a menu with one primary command and one secondary command. Every button is represented with a NavigationButtonInfo control, which has a key property called PageType. You can use it to specify which is the page of your application connected to this button: when the user will tap on it, he will be automatically redirected to that page. Additionally, there are two other properties to customize the navigation experience:

  • ClearHistory is a boolean that, when it’s set to true, forces the cleanup of the back stack. It’s typically used with the main section of the application, to avoid circular navigation issues (when the user is on the main page of the app and the back button is still enabled).
  • PageParameter is helpful if you need to pass a parameter to the landing page, which can be retrieved using the OnNavigatedTo() method.

The look & feel of the button is up to the developer: inside the NavigationButtonInfo control you can include any XAML control. In the sample you can see a definition that will help you to recreate the same look & feel of native apps: an icon (defined by the SymbolIcon control) and a label (defined with a TextBlock control). Here is how the previous code becomes when the app is running:

 

clip_image014

clip_image016

The HamburgerMenu control, to work properly, needs a reference to the NavigationService, which is the service provided by Template10 to handle the navigation. This reference is configured in code-behind, thanks to the NavigationService property offered by the control:

public sealed partial class Shell : Page
{
    public Shell(NavigationService navigationService)
    {
        this.InitializeComponent();
        Menu.NavigationService = navigationService;
    }
}

In the next section we’re going to learn how to pass a reference to the NavigationService to the page that contains the HamburgerMenu control, like we’ve seen in the previous sample.

Create the shell

In the previous sections we’ve learned how, thanks to Template10, it’s easy to implement a navigation pattern based on the hamburger menu. However, we have a problem: the HambrgerMenu is just a control and, consequently, you need to add it to a page but, at the same time, you need to handle that every page of your application will reuse the same menu.

Let’s introduce the shell, which is a special page of the application that will act as a container for the pages of the application. By using this approach, the HamburgerMenu control will be defined just once inside the shell and, consequently, we won’t have to include it in every page of the application. The first step is to create an empty page in our project and to repeat the steps we’ve already done in the previous section, which are including a HamburgerMenu control and connecting the NavigationService, like in the following sample:

<Page
    x:Class="HamburgerSample.Views.Shell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:views="using:HamburgerSample.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Template10.Controls"
    x:Name="ThisPage"
    mc:Ignorable="d">

    <controls:HamburgerMenu x:Name="Menu">
        
        <controls:HamburgerMenu.PrimaryButtons>
            <controls:NavigationButtonInfo PageType="views:MainPage" ClearHistory="True">
                <StackPanel Orientation="Horizontal">
                    <SymbolIcon Symbol="Home" Width="48" Height="48" />
                    <TextBlock Text="Home" Margin="12, 0, 0, 0" />
                </StackPanel>
            </controls:NavigationButtonInfo>

            <controls:NavigationButtonInfo PageType="views:DetailPage" >
                <StackPanel Orientation="Horizontal">
                    <SymbolIcon Symbol="Calendar" Width="48" Height="48" />
                    <TextBlock Text="Calendar" Margin="12, 0, 0, 0" />
                </StackPanel>
            </controls:NavigationButtonInfo>
        </controls:HamburgerMenu.PrimaryButtons>

        <controls:HamburgerMenu.SecondaryButtons>
            <controls:NavigationButtonInfo PageType="views:SettingsPage">
                <StackPanel Orientation="Horizontal">
                    <SymbolIcon Symbol="Setting"  Width="48" Height="48" />
                    <TextBlock Text="Settings" Margin="12, 0, 0, 0" />
                </StackPanel>
            </controls:NavigationButtonInfo>
        </controls:HamburgerMenu.SecondaryButtons>

    </controls:HamburgerMenu>
</Page>

public sealed partial class Shell : Page
{
    public Shell(NavigationService navigationService)
    {
        this.InitializeComponent();
        Menu.NavigationService = navigationService;
    }
}

Now we need to:

  1. Configure the page we’ve just created as container for all the page of our application, by replacing the standard frame.
  2. Pass to the page a reference to the NavigationService object

Both operations can be achieved in the BootStrapper class: we’re going to use the OnInitializeAsync() method, which is performed right before the app triggers the navigation to the main page.

sealed partial class App : BootStrapper
{
    public App()
    {
        this.InitializeComponent();
    }

    public override Task OnInitializeAsync(IActivatedEventArgs args)
    {
        var nav = NavigationServiceFactory(BackButton.Attach, ExistingContent.Include);
        Window.Current.Content = new Views.Shell(nav);
        return Task.FromResult<object>(null);
    }

    public override Task OnStartAsync(BootStrapper.StartKind startKind, IActivatedEventArgs args)
    {
        NavigationService.Navigate(typeof(Views.MainPage));
        return Task.FromResult<object>(null);
    }
}

The first step is to use the NavigationServiceFactory method to retrieve the proper reference to the NavigationService. This way, we can pass it as a parameter when we create a new instance of the Shell page. Then we assign this instance to the Window.Current.Content property, which holds a reference to the main frame of the application, which will act as a container for the pages. In a standard application, this property is simply set with a new instance of the Frame class.

Thanks to this line of code, the application won’t use anymore an empty frame as a container for your pages, but the Shell page, which contains the HamburgerMenu definition. The final result will be that all the pages of your application will share the same menu we have defined in the Shell page.

HamburgerMenu and PageHeader: the dynamic duo

The PageHeader and HamburgerMenu controls have been designed to work together. The best visual layout, in fact, can be achieved when the various sections in a hamburger menu are handled with a page that has a PageHeader control to define the header.

Moreover, both controls supports the adaptive layout, which is the new approach introduced in Windows 10 to help developers building a single binary package that can runs on every platform (vice versa, on Windows and Windows Phone 8.1 you needed to create and publish two different packages). Adaptive layout is an approach which is already widely used in the web world and it simply means that the user interface has to properly react to the changes in the window’s size, so that the app can always offer the best user experience, regardless if it’s running on a mobile phone or on a console.

Both controls implements this approach to optimize the user experience:

  • By default, the PageHeader control doesn’t add any margin to the text of the header. When the app’s windows is wide enough, the HamburgerMenu control will always be visible in minimal mode (which means that the icons will always be visible, while the labels will be displayed only when the panel is open). Consequently, there’s no need to artificially add a margin in the PageHeader control: the hamburger button of the menu already takes care of it.
  • When the size of the window is smaller (for example, on a phone) there isn’t enough space to keep the menu icons always visible. Consequently, the panel is completely hidden: only the hamburger button will be visible. In this scenario, the PageHeader control adds a 48px margin on the left, to avoid that the header’s text overlaps with the button.

This behavior is automatically handled by both controls. However, you have the chance to define which is the size of the window that should trigger the two visual states, by using the VisualStateNarrowMinWidth and VisualStateNormalMinWidth properties. Take a look at the following sample:

<controls:PageHeader Text="Main page" Frame="{x:Bind Frame}"
                     VisualStateNarrowMinWidth="0"
                     VisualStateNormalMinWidth="700" />

With this configuration:

  • When the width of the window is between 0 and 700, the control applies the VisualStateNarrow visual state, which is the minimal one (the panel is hidden and the header’s text is shifted).
  • When the width of the window is bigger than 700, instead, the control applies the VisualStateNormal visual state, which is the standard one (the panel is visible in minimal mode and a shift of the header’s text isn’t required).

The same properties are available also in the HamburgerMenu control: of course, to get the best result, it’s important that the two properties are set in the same way on both controls. The following images will help you to understand better the difference between the two states: the first one is the normal state, the second one is the narrow state.

clip_image017

clip_image019

If you want to disable this behavior for the PageHeader control (for example, because you aren’t providing a hamburger menu based navigation experience and, as such, the shift of the header’s text can break your layout) it’s enough to set the VisualStateNarrowMinWidth property to –1.

Wrapping up

In this post we’ve learned how to use the custom controls offered by Template10. In the next post, instead, we’ll see more C# code, since we will focus on how Template10 can make easier the implementation of the MVVM pattern.

As a reminder, you can find Template10 on GitHub (http://github.com/Windows-XAML/Template10/). The repository contains also a set of samples to start playing with the controls described in this post. Happy coding!

Posted in Universal Apps | Tagged , , | 1 Comment