Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Databinding in Silverlight applications

0.00/5 (No votes)
11 May 2010 2  
In this article, you will learn the basic concepts of simple data binding in a Silverlight application.

Table of Contents

Overview

In this article, you will learn the basic concepts of simple data binding in a Silverlight application. I have covered the different types of binding modes available and how to use them declaratively and programmatically. We will also see how to do binding for a collection, the importance of the INotifyPropertyChanged interface method, and the ObservableCollection class. Our ultimate goal is to fetch information from a back-end or from a .NET object and show it in the user interface.

These are some of my other articles on Silverlight technology:

Introduction to Databinding

Databinding is the process of establishing a connection between a source and target. In Silverlight databinding, the source is the CRL object and the target is Silverlight controls (XAML Elements). Let me show you a visual.

Binding Modes

There are three types of data binding that happens in Silverlight applications between a source and target.

  1. OneTime data binding
  2. OneWay data binding (default mode)
  3. TwoWay data binding

OneTime data binding: As the name suggests, data binding happens between the source and target only once. In this binding, the source (CRL object) data will bind with the target (XAML element) only when the page executes the first time. Later on, any changes made in the source will not be reflected back in the target element. You will prefer to use this binding mode to reduce overhead if you know that the source property won’t change.

OneWay data binding: In this data binding, the source will immediately inform about changes to the target control. We will be using this binding only for frequently changed elements. This is the default mode.

TwoWay data binding: This happens in bidirectional mode. Whenever any change occurs in the backend or the CRL object, it will inform to the XAML controls immediately, and vice versa.

Binding in Silverlight requires three things:

  1. The first thing we need is target UI element’s property. This can be a TextBox control's Text property or ListBox control’s ItemsSource property etc… You can call this the DependencyProperty of a FrameworkElement.
  2. The source object that contains the data that flows between the source and the target. The source can be any CLR object.
  3. A binding object to handle the communication between these two.

To implement data binding in XAML code, you need to implement a binding statement. Here is the syntax for how to use a binding statement in XAML:

The binding is created in XAML using the {Binding ...} syntax.

<TextBox x:Name="tbFirstName" Text="{Binding Path=FirstName, Mode=OneTime}" 
         Grid.Column="2" Grid.Row="1"></TextBox>

The binding statement has many properties, but here is a list of frequently used properties of the Binding statement:

  • Path is the name of the source property to get the data from.
  • Mode is the connection type (OneTime, OneWay, and TwoWay) between the source and the target.
  • Source is the standard CLR object that contains the data.
  • Converter is used to specify the converter object that is called by the binding engine to modify the data as it is passed between the source and the destination.
  • Converter Culture specifies a parameter that can be passed to the conversion of the data.
  • Conversion Parameter specifies a parameter that can be passed to the converter.

What is DataContext?

There is one more important thing in database binding, which is the DataContext property. The DataContext property is used to set or get the data context for a FrameworkElement when it is participate in data binding.

Data context is inherited. If you set the data context on a parent element, all its children will use the same data context. A child element can override this behavior by setting the Source property on its binding object or by setting its DataContext, which will then apply to all its children.

The DataContext property can be set in the parent control or for each child control. The only advantage of setting it in the parent control is, you don’t need to repeat it for each child control.

Here is an example of how to set the DataContext property in the parent control and use it in the child controls.

BindingModesExamples.xaml
<UserControl x:Class="SampleCode.BindingModesExamples"
     xmlns:local="clr-namespace:SampleCode"
     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"    >
   <UserControl.Resources>
       <local:Employee x:Key="employeeInfo" FirstName="Anjaiah" LastName="Keesari"/>
   </UserControl.Resources>  
   <Grid x:Name="LayoutRoot" 
      DataContext="{StaticResource employeeInfo}" 
      Background="LightCyan" Width="500" Height="300" 
      HorizontalAlignment="Left" >
        <Grid.ColumnDefinitions >
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="200" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        
        <TextBlock Text="First Name" Grid.Column="1" Grid.Row="1"></TextBlock>
        <TextBox x:Name="tbFirstName" Text="{Binding Path=FirstName, Mode=OneTime}" 
                 Grid.Column="2" Grid.Row="1"></TextBox>
        
        <TextBlock Text="Last Name" Grid.Column="1" Grid.Row="2"></TextBlock>
        <TextBox x:Name="tbLastName" Text="{Binding Path=LastName, Mode=OneTime}" 
                 Grid.Column="2" Grid.Row="2"></TextBox>
        
        <TextBlock Text="Email ID" Grid.Column="1" Grid.Row="3"></TextBlock>
        <TextBox x:Name="tbEmailID" Text="{Binding Path=EmailID, Mode=OneTime}" 
                 Grid.Column="2" Grid.Row="3"></TextBox>
    </Grid>
</UserControl>

Most of the times, you may not want to bind the data just using XAML; you can also do the same thing using your favorite programming language like C#. Binding can also be performed programmatically. What you need to do is just create a new binding object and call the SetBinding() method to perform the binding between the source and the target. Here is a sample code to do that.

BindingModesExamples.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
namespace SampleCode
{
    public partial class BindingModesExamples : UserControl
    {
        public BindingModesExamples()
        {
            InitializeComponent();
            Loaded+=new RoutedEventHandler(BindingModesExamples_Loaded);
        }
        //Example of binding useing code 
        private void BindingModesExamples_Loaded(object sender, RoutedEventArgs args)
        {
            Employee employee = new Employee();
            employee.EmailID = "Keesari_anjaiah@yahoo.co.in";
            Binding binding = new Binding()
            {
                Source = employee,
                Path = new PropertyPath("EmailID"),
                Mode = BindingMode.OneTime
            };
            tbEmailID.SetBinding(TextBox.TextProperty, binding);
        }
    }
}

Before we proceed further, let me show you the .NET object which I am using for each example. Do not worry about the PropertyChanged concepts in this class which we will be talking about soon. Just continue reading this article completely in order to understand the data binding concepts.

Employee.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace SampleCode
{
    public class Employee :INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }
        private int employeeID;
        public int EmployeeID
        {
            get
            {
                return employeeID;
            }
            set
            {
                if (employeeID != value)
                {
                    employeeID = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("EmployeeID"));
                }
            }
        }
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set
            {
                if (firstName != value)
                {
                    firstName = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("FirstName"));
                }
            }
        }
        private string lastName;
        public string LastName
        {
            get { return lastName; }
            set
            {
                if (lastName != value)
                {
                    lastName = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("LastName"));
                }
            }
        }
        private String emailID;
        public String EmailID
        {
            get
            {
                return emailID;
            }
            set
            {
                if (emailID != value)
                {
                    emailID = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("EmailID"));
                }
            }
        }
        private string title;
        public string Title
        {
            get { return title; }
            set
            {
                if (title != value)
                {
                    title = value;
                    OnPropertyChanged(new PropertyChangedEventArgs ("Title"));
                }
            }
        }
        private DateTime dateOfBirth;
        public DateTime DateOfBirth {
            get { return dateOfBirth; }
            set {
                if (dateOfBirth != value)
                {
                    dateOfBirth = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("DateOfBirth"));
                }
            }
        }
    }
}
Output:

Binding Collections

Now that we are clear on single object data binding, let’s talk about collections of objects.

ListBox is one of the controls used to bind collections of data. All collection control classes are represented by the ItemsControl class. Binding a collection to an ItemsControl is as simple as assigning the ItemsSource property to some collection and assigning the DisplayMemberPath to a property of a collection item.

TwoWayBindingExamples.xaml
<UserControl x:Class="SampleCode.TwoWayBindingExamples"
    xmlns:local="clr-namespace:SampleCode"
    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">
    <UserControl.Resources>
        <local:Employees  x:Key="Employees" />
    </UserControl.Resources>
    <StackPanel DataContext="{StaticResource Employees}" 
              Background="LightCyan" Width="500" Height="300" >
        <TextBox x:Name="tbDescription"
            Text="{Binding Path=SelectedItem.Title, ElementName=lbEmployees, Mode=TwoWay}"
            HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Width="325" />
        <ListBox x:Name="lbEmployees" ItemsSource="{Binding}"
            DisplayMemberPath="Title" HorizontalAlignment="Left" VerticalAlignment="Top"
            Margin="10" Width="323" />
    </StackPanel>
</UserControl>
Employees.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
namespace SampleCode
{
    public class Employees : ObservableCollection<Employee>
    {
        public Employees()
        {
            this.Add(new Employee()
            {
                EmployeeID=1,
                FirstName = "Nancy",
                LastName = "Davolio",
                Title = "Sales Representative",
            });
            this.Add(new Employee()
            {
                EmployeeID = 2,
                FirstName = "Andrew",
                LastName = "Fuller",
                Title = "Vice President, Sales",
            });
            this.Add(new Employee()
            {
                EmployeeID = 3,
                FirstName = "Janet",
                LastName = "Leverling",
                Title = "Sales Manager",
            });
        }
    }
}

Change Notification

As we discussed earlier, we need to allow changes made in the data source to reflect immediately on the target. How is this possible? This is possible by implementing the INotifyPropertyChanged interface. It is a descendent of ObservableCollection<T>, and the interface is implemented for you. What you need to do is take the namespace System.ComponentModel to implement INotifyPropertyChanged interface.  This has the single method called PropertyChanged(). When setting a property value, you need to call the OnPropertyChanged() method if any value changes.

ObservableCollection

To provide notifications for collection changes (new item added, removed, or entire list refreshed), we need to inherit our collection object from ObservableCollection<T>. Add a reference to System.Collections.ObjectModel before using ObservableCollection.

Silverlight provides the ObservableCollection<T> class, which is a base class data collection that implements the INotifyCollectionChanged interface, as well as the INotifyPropertyChanged interface. It also has the expected collection support, defined by deriving from the Collection<T> class.

Note: Update occurs when the TextBox loses focus.

Output:

Conclusion

I hope you enjoyed my article. Please do not forget to write your comments on this article, which is very important for me.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here