Silverlight Binding

 

Binding is a fundamental part of Silverlight and allows developers to create a relationship between a UI property and a CLR object. Unfortunately, it can be a little confusing at first. Is it worth the trouble getting use to the syntax?

 

<object property=”{Binding}” …/>

 

It’s entirely possible to update the Silverlight presentation layer without using binding. Although with the use of binding you can make your code more reusable and easier to extend. Especially if you have multiple web requests that update the view. I’m not saying binding is a silver bullet. It can be very frustrating to track down issues and getting the syntax correct. But used in the right situations it can be very useful.

 

I’m not a Silverlight expert and I won’t be able to cover every detail of binding. I’ll start by covering some basic syntax. Then give an example using notification properties and dependencies properties. Then I will finish with a list of links and resources to find more information about MVVM and Silverlight 4.

 

 

Basic Binding Syntax

 

Let’s look at an example using an object named Cat and we will bind to the Speak property.

namespace BindingPatterns.ViewModel
{
    public class Cat
    {
        public string Speak { get; set; }
    }
} 

 

From now on I won’t include this much XAML detail but I wanted to be clear on the first example. Notice the name space of where the Cat class is located is added.

<usercontrol x:Class="BindingPatterns.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"
    xmlns:data="clr-namespace:BindingPatterns.ViewModel"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <usercontrol.Resources>
        <data :Cat x:Key="ViewModel" Speak="meow" />
    </usercontrol>

    <grid x:Name="LayoutRoot">
        <textblock x:Name="CatSound" Text="{Binding Path=Speak, 
                Source={StaticResource ViewModel}}"></textblock>
    </grid>

 

I know this isn’t very useful but it’s only to demonstrate the binding. What happens first in this example is the Cat class is instantiate as a static Resource. Then we set the Speak property to “meow”. Finally we bind the TextBlock to the Speak property of that class. We have to include the Source attribute to tell where the CLR binding is located.

 

Another way we could do this is using the data context. Once “ViewModel” (which is the Cat class) is added to the DataContext we can reference directly in the TextBlock via the public property “Speak”.

<grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModel}}">
    <textblock x:Name="CatSound" Text="{Binding Path=Speak}"></textblock>
</grid>

 

To simplify more you can leave off the Path and just use the following.

<textblock x:Name="CatSound" Text="{Binding Speak}"></textblock>
 

 

Notice the TextBlock no longer needs a Source extension because it looks in the DataContext by default. A reason to use the DataContext is child controls can also access this. When you add a binding to that control first it will check the current UserControl and if it can’t be found it will check the parents DataContext. For example, let’s move the TextBlock into a separate user control called CatControl. Then we could get the same result as above using this.

<grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource ViewModel}}">
        <control :CatControl></control>
</grid>

 

Instead of using the Static Resource you can set the DataContext in C# as long as the control is initialized by doing the following.

public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            DataContext = new Cat { Speak = "meow in C#" };
        }
    }

 

The binding syntax also supports drilling into properties of properties using dot notation.


<textblock x:Name="CatActivity" Text="{Binding CatActivity.Scratch}"></textblock>


var activity = new CatActivity(){Scratch="scratchy"};
DataContext = new Cat { Speak = "meow in C#", CatActivity = activity };

 

Binding with Notification and Dependency Properties

 

An example where binding, notifications, and dependency properties show their power is when you need to make multiple Async web requests which have dependencies.


 

To use notifications you need to inherit from INotifyPropertyChanged. Then you can setup properties that will notify a binding when they change. For example, to update the quote we could have a notification property setup that would get updated by the request callback.

        private Quote _quote;
        public Quote Quote
        {
            get { return _quote; }
            set
            {
                _quote = value;
                NotifyPropertyChanged("Quote");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }


<textblock x:Name="Price" Text="{Binding Quote.Price}"/>
<textblock x:Name="Price" Text="{Binding Quote.PercentChange }"/>

 

 

For the Chart State we can setup a dependency property that will change the chart user control as needed. In this case we do some drawing and background changes.

public static readonly DependencyProperty ChartStateProperty = DependencyProperty.Register(
            "ChartState",
            typeof(StateIndicator),
            typeof(LineChartControl),
            new PropertyMetadata(StateIndicator.NoChange, OnChartStateChanged));

        private static void OnChartStateChanged(DependencyObject d, 
                              DependencyPropertyChangedEventArgs e)
        {
            var lineChart = (LineChartControl)d;
            lineChart.CreateStateBackground((StateIndicator)e.NewValue);
            lineChart.ChangeLineColor((StateIndicator)e.NewValue);
        }

 

For a simpler example of notification binding we can go back to the cat example. Let’s setup the notification.

  public class Cat : INotifyPropertyChanged
    {
        public string Speak { get; set; }

        private CatActivity _catActivity;
        public CatActivity CatActivity
        {
            get { return _catActivity; }
            set
            {
                _catActivity = value;
                NotifyPropertyChanged("CatActivity");
            }
        }

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }


         public event PropertyChangedEventHandler PropertyChanged;

     }

 

Then let’s make a button and a few fields to bind to the CatActivity property. Don’t take this as good coding practice. This is just a simplistic example to show how the notifications can be triggered.


        public Cat MyCat { get; set; }
        public MainPage()
        {
            InitializeComponent();

            var activity = new CatActivity(){
                                   Scratch="scratchy", 
                                   Run="scramble"
                                   };
            MyCat = new Cat { 
                       Speak = "meow in C#", 
                       CatActivity = activity};
            DataContext = MyCat;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var newActivity = new CatActivity() { 
                               Scratch = "scratchy again", 
                               Run = "scramble again too" };
            MyCat.CatActivity = newActivity;
        }

 

When you click the button the following bindings will show “scratch again” and “scramble again too”.


<stackpanel>
    <button Click="Button_Click"></button>
    <textblock x:Name="CatSound" Text="{Binding Speak}"></textblock>

    <textblock x:Name="CatActivityScratch" Text="{Binding CatActivity.Scratch}">
    </textblock>

    <textblock x:Name="CatActivityRun" Text="{Binding CatActivity.Run}">
    </textblock>
</stackpanel>

 

 

SL4 and MVVM Links

 

Leave a Reply

Your email address will not be published. Required fields are marked *