Data Binding and Model-View-ViewModel in UWP Part 1

Data Binding is a powerful and important tool in Windows development. Whether targeting UWP, WPF, Xamarin.Forms, or something else, binding is crucial to your app design. The idea of binding is simple. It is used to connect a binding target to a binding source. The binding target is typically the property of a control or some type of UI element. This could be the text of a label, whether a switch is on, or a selection in a combo box. The binding source is a property from another class, usually a viewmodel or model. This is the data that tells the binding target what to display. 

Now, we have a high level understanding of data binding, but why are we using it? The main purpose is to decouple our UI code from our non-UI code. This strategy is utilized in Microsoft’s recommended UI architectural design pattern, Model-View-ViewModel (MVVM), and has a number of benefits. Decoupling different sections of your code creates a separation of concerns. Testing becomes easier since your code is more isolated, different programmers can focus on different parts of the project (front end and back end programmers can simultaneously work on different aspects), and the code is much more maintainable and reusable. 

Model-View-ViewModel

Although somewhat self-explanatory, let’s take a quick look at the 3 layers of the MVVM paradigm. The model is the first layer. This houses all of your software’s business data. Core app logic, class definitions, and data can all typically be found here. The view is the user interface of your project. In UWP, which we are using for this project, this is done with XAML files that define your views and controls. Code-behind files can also be used to further define elements of the view. The viewmodel binds and processes information between the model and view classes. Now that we have a quick idea of the elements of MVVM and data binding, let’s jump into a project and see it in action.

Our Test Project

Let’s quickly lay out what we want to do for our project. We are going to create a UWP application. It is going to be a single page with tabs on it. One tab will have a list of our favorite foods. The other tab will have a list of all included foods with a toggle switch to tag them as a favorite.

The project will need one model class where we will define our food model, one view class where we layout the UI for the page, and one viewmodel class where we get everything to work together. Let’s get started!

Create Our Project

I am going to do this project in Visual Studio on a Windows device targeting UWP. You could easily do this project in Visual Studio for Mac and target Xamarin.Forms, although some of the UI code will be slightly different.

Open Visual Studio and go to File->New->Project… Select Windows Universal in the left pane under Visual C#, and select Blank App (Universal Windows). Feel free to name the app anything you want (I’ll call mine MyFavoriteFoods), and click OK. I’m going to target Windows 10, version 1809 and set the minimum version to Windows 10 Creators Update. Press OK. Our project is now created. 

Start by deleting MainPage.xaml and its code-behind file, MainPage.xaml.cs. I want to create my own view file inside a folder to better delineate the layers of the project. 

Creating our Model

Right click on the MyFavoriteFoods project, and click Add->New Folder. Name the folder “Model” and press enter. Right click your new model folder and select Add->New Item… Select Class and name it FoodModel.cs. Press Add. We will start by just adding the bare bones properties to this class. Make the class public and add properties to make it look like this.

public class FoodModel
{
    public string Name { get; set; }
    public bool IsFavorite { get; set; }
}

You can see, we have a string property for the name of the each food and a bool for whether this is a favorite food or not. Let’s move on to our View.

Creating our View

Create another folder in the project; this time called View. Create a Blank Page inside the folder named FoodView.xaml. 

Before we make any changes on this page, let’s set this new view as our first page for startup. Open the App.xaml.cs file. At the top, add the view namespace: “using MyFavoriteFoods.View”. Then change the following line to set the first page as our new view, FoodView.xaml. 

rootFrame.Navigate(typeof(MainPage), e.Arguments);
rootFrame.Navigate(typeof(FoodView), e.Arguments);

Let’s go back to FoodView.xaml. We’re going to put a large title at the top, and then a pivot to swap between our favorite foods and all foods. Add the following code to the page.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height = “auto”/>
        <RowDefinition Height = “*”/>
    </Grid.RowDefinitions>
    <TextBlock Text=“Food” FontSize=“30” Margin=“10,0,0,0”/>
    <Pivot Grid.Row = “1”>
        <PivotItem Header=“Favorite Foods”>

        </PivotItem>
        <PivotItem Header=“All Foods”>

        </PivotItem>
    </Pivot>
</Grid>

As you can see, we created two rows inside our grid. The first has an auto height so that it is allocated the amount of space that its contents need. The second row is set to height “*” so that it is allocated the remaining height of the grid. We use a text block in the first row of the grid to set a title of “Food” for the page. We use a pivot in the second row with two pivot items. The first is given a header of “Favorite Foods” and the second is “All Foods.” Feel free to run the project. You will see what we laid out and be able to select the pivots. We still need to fill out their content. Let’s move on to our viewmodel, and then, we will come back to finish the view.

Creating Our ViewModel

We need to create another folder in our project. This one should be called “ViewModels.” Create a new class file inside the folder and call it “FoodViewModel.cs.” This will be the viewmodel for our FoodView class.

Let’s start by creating two instance variables for the class. One will be a list that will house all of the foods that are in our universe. The second will be an ObservableCollection of all of our favorite foods. It is helpful to use an ObservableCollection as the type for our favorite foods because we will be adding and removing foods from this collection. The all foods collection will remain constant as there is currently no way to add new foods while the project is running. The ObservableCollection provides a notification to its binding target when items get added, removed, or when a whole list is refreshed. This is helpful for updating our view as selections get manipulated.

First, we need to add the Model namespace to the class, and another namespace to use ObservableCollection objects. At the top of the page, add the following lines.

using MyFavoriteFoods.Model;
using System.Collection.ObjectModel;

Then, make the class public like this.

public class FoodViewModel

Next, create the instance variables in a manner like this.

public List<FoodModel> AllFoods = new List<FoodModel>();

public ObservableCollection<FoodModel> FavoriteFoods = new ObservableCollection<FoodModel>();

ViewModel Methods

Now, we need to load initial data into these collections. This data would normally come from either a local or external server, but that is far beyond the scope of this tutorial. We could create a data section to house this data, as well, but again, the purpose of this is to focus on MVVM and binding. We are simply going to load the data in a method in the viewmodel. This is not typical work for a viewmodel in a larger scale project, and if this project was more than one page, we would certainly want to move the data elsewhere. Let’s add a constructor method for the viewmodel and call another method inside it.

public FoodViewModel()
{
    LoadFoodData();
}

Now, let’s define that method to populate data in the collections.

private void LoadFoodData()
{
    AllFoods.Add(new FoodModel()
    {
        Name = “Apple”,
        IsFavorite = false
    };

    AllFoods.Add(new FoodModel()
    {
        Name = “Banana”,
        IsFavorite = false
    };

    AllFoods.Add(new FoodModel()
    {
        Name = “Pizza”,
        IsFavorite = true
    };

    AllFoods.Add(new FoodModel()
    {
        Name = “Spinach”,
        IsFavorite = false
    };

    AllFoods.Add(new FoodModel()
    {
        Name = “Turnip”,
        IsFavorite = false
    };

}

foreach(FoodModel eachFood in AllFoods)
{
    if (eachFood.IsFavorite)
    {
        FavoriteFoods.Add(eachFood);
    }
}

Conclusion

Now, we have our collections of data defined and available to use. In part 2 of this tutorial, we will bind these collections to their corresponding pivots so that each collection is displayed in the user interface. On the all foods pivot, you will be able to select whether a particular food is one of your favorites. Upon selecting or unselecting a food, the binding change will alert our code to update the collection of favorite foods. We set up a great MVVM structure in part 1, but there is a lot of exciting coding to look forward to in part 2. As always, thanks for reading the HangZone blog!