Data Binding in MVVM – Bind views with viewmodels!

if(you_liked_app_philosophy)
start_here;else
goto Serious_talks;

So as per said in my last write up, Im supposed to give a glimpse on how viewmodel talks with views and how models supply them data. Im now gonna get straight back to the car scenario. Think of that car again. We had three parts, the engine (model), the body (view) and the driver (the viewmodel). You drive well, your car seems nice and clean, you roughhouse, eh! you might make it work on the outside but someday when you feel like upgrading that stuff, the only thing you’re gonna say, “what on earth did I do there”? If you ask me how do I know this? Brother I did the same mistake over and over again. (Yes, as per description of insanity from Far Cry 3, I was insane!)

So, the part I want to say here, your cars body will say how you drive. If it’s nice shiny and clean it says you’re a clear one, if it isn’t it says something else. So, the body (view) shows the signs you(viewmodel) leave on it. And how you bind it? Press the buzzer please!

“Data Binding” you say sire? You’re exactly right me lord.

Let’s Dive in.

Serious_talks:

Okay the serious stuff is in. I started with a pretty standard XAML (I believe you’ve met with standard Windows Phone development process, if you didn’t, you should and come back here). I added a panorama control, renamed it’s title to Star Cineplex. I added two panoramaitem control to cover “Now Showing” and “Coming Soon”. Pretty basic stuff actually. So, the xaml looks like below:

<phone:PhoneApplicationPage
x:Class="Star_Cineplex.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>

</Grid.RowDefinitions>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:Panorama Title="Star Cineplex">
<phone:PanoramaItem Header="Now Showing">
<ListBox Name="NowShowingList"  >

</ListBox>
</phone:PanoramaItem>
<phone:PanoramaItem Header="Coming Soon">

</phone:PanoramaItem>
</phone:Panorama>

</Grid>

</Grid>

</phone:PhoneApplicationPage>

So I guess it looks pretty simple to you.  You might want to look into the Listbox named “NowShowingList” as magic is gonna happen there. So, yes, the viewmodel mostly talks with view through data binding. . And Im not gonna tell much on data binding, so you should go for some basic data binding tutorials first. Without it, all of these would seem nonsense to you. True Story!

Let’s provide a dummy model. The model is nothing but a class who states how the actual data is represented. Let’s make a very simple Movie class. Shall we?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Star_Cineplex
{
    class Movie: INotifyPropertyChanged
    {
        private string name;
        private int year;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                if (this.name != value)
                {
                    this.name = value;
                    this.RaisePropertyChanged("Name");
                }
            }
        }

        public int Year
        {
            get
            {
                return this.year;
            }
            set
            {
                if (this.year != value)
                {
                    this.year = value;
                    this.RaisePropertyChanged("Year");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }
}

Lets have a quick talk on the model then. The first thing you need to notice is the use of the INotifyPropertyChanged interface use. This very interface works as a secret serum for almost everything written on a MVVM app. You might ask why? This guy pokes you when a property changes its value in the class its implemented. Like if something changes the year property of the Movie class, this guy will jump up and say “Hello, somebody just changed the year property, care to do something?” Funny, ha? As funny as it sounds, believe me, this is one of the guys who you would see most in MVVM. So, lets have a lil discussion on this interface.

INotifyPropertyChanged interface basically raises an event named PropertyChanged. All you have to do is declare the event explicitly along with a method that will be executed generally for all properties that are monitored for a change. The method is optional if you’re cool with anonymous functions or lambda expressions. 😉

If you’re not, don’t leave. I’m even breaking it more up for you. You see in the set {} method of the property Year and Name whenever I found a change in the value I invoked the RaisePropertyChanged method to invoke the event to let the user know something has changed the property. We’ll actually go for a template or definite interfaces for models later so we don’t have to do this every time we write a model. But that’s later. Let’s focus on this simple area right now. 🙂

So, the model is pretty simple as it seems, so for now let’s forget the model, we’re gonna provide sample data here somehow to test how things work within the view and viewmodel. So, we need a viewmodel first. Don’t we? I’m posting a very basic viewmodel here. Later we would organize and sanitize the workflow more so we can extend stuff fast. But for now, for clarity’s sake let’s keep it very simple. Don’t worry the explanation comes just after. I believe the code talks more to a developer than anything.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace Star_Cineplex
{
    class MovieViewModel
    {
        private ObservableCollection<Movie> movieDataSource;
        private ICommand loadDataCommand;

        public MovieViewModel()
        {
            this.movieDataSource = new ObservableCollection<Movie>();
            LoadData();
        }

        private void LoadData()
        {
            this.movieDataSource.Add(new Movie() { Name="Despicable Me 2", Year=2013});
            this.movieDataSource.Add(new Movie() { Name = "Man Of Steel", Year = 2013 });
            this.movieDataSource.Add(new Movie() { Name = "Wolverine", Year = 2013 });
        }

        public ObservableCollection<Movie> MovieDataSource
        {
            get
            {
                if (this.movieDataSource == null)
                {
                    this.movieDataSource = new ObservableCollection<Movie>();
                }
                return this.movieDataSource;
            }
        }

    }
}

I believe this is by far the simplest Viewmodel you can write. You see, all I did is I populated the MovieDataSource list with some data.

So, if you read the link I gave you before on Data Binding you’d might ask why Im not yet binding? Let’s do that! Remember the ListBox named “NowShowingList”? Change it into this one below:

<ListBox Name="NowShowingList" ItemSource={Binding MovieDataSource}  >
<ListBox.ItemTemplate>
 <DataTemplate >
 <StackPanel>
 <TextBlock Text="{Binding Name}" FontSize="{StaticResource PhoneFontSizeLarge}"></TextBlock>
 <TextBlock Text="{Binding Year}"></TextBlock>
 </StackPanel>
 </DataTemplate>
</ListBox.ItemTemplate>
</Listbox>

Wait, wait, wait! What did I do here? The first change you will see that I declared the itemsource of the listbox and I binded it with MovieDataSource, the one in our ViewModel!
This is done to show the movie list we created into the ListBox.

You might ask why did I use ObservableCollection? The interesting part is whenever you bind an ObservableCollection object as a ListBox’s itemsource, you dont have to worry about any changes in the list, the UI will adjust the changes automatically, no hassle needed! 😀 So, I mean if somehow the ObservableCollection gets bigger, the list in the UI will automatically grow bigger! So, if you add/remove a movie in the MovieDataSource, the NowShowingList ListBox will automatically grow bigger.

And I defined a data template to show the data. The datatemplate actually defines how each of your rows of your listbox will look like. I only used two texblocks here. And see! I binded the first one with Name and the second one with Year! Why? Because remember what was in the MovieDataSource? Yes, our model movie objects. It had two properties, Name and Year. We want both of them in our list. So, we binded both of them.

Now the question rises. Is this all? Aren’t we forgetting something?

Yes we are actually forgetting one thing. Kindly open the MainPage.xaml.cs and add the DataContext like this.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using Star_Cineplex.Resources;

namespace Star_Cineplex
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            this.DataContext = new MovieViewModel();

        }

    }
}

So, what is the DataContext? the DataContext is the glue that holds them all. DataContext is usually defined by ViewModels as they provide the representable data to the view. I could’ve shown you many ways to bind data to the view but choosing a very simple example like this had only one objective and that is to let you know in MVVM to bind your view to viewmodel you only have to assign the DataContext. The rest is a breeze!

One other thing! I used a INotifyPropertyChanged in my model but never actually used it. We’ll continue this journey a bit more with ICommand usage and of course more binding usage with INotifyPropertyChanged interface in the upcoming ones.

Oh! This is how it looks now!

Screenshot

So, until next time, goodbye pals!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s