Category Archives: Data Binding

Introduction to Multi Binding and Multi value converter using IMultiValueConverter & MultiBinding

For Introduction to Value Converters, see the post here.

For more information on mode property, see the the post on mode here.

MultiBinding allows us to bind a binding target property to a list of source properties and then apply logic to produce a value with the given inputs. This example demonstrates how to use MultiBinding. The following example produces a TextBox that adds the numbers in TextBox1 and TextBox2 and puts the result into TextBox3. Here we have two source properties and the one target property. When you enter numbers in the TextBox1 and TextBox2 , the converter comes into play and automatically adds them and puts the result into TextBox3. The values of the Mode and UpdateSourceTrigger properties determine the functionality of the MultiBinding and are used as the default values for all the bindings in the collection unless an individual binding overrides these properties. For example, if the Mode property on the MultiBinding object is set to TwoWay, then all the bindings in the collection are considered TwoWay unless you set a different Mode value on one of the bindings explicitly.

In the following code, AddConverter implements the IMultiValueConverter interface. AddConverter takes the values from the individual bindings and stores them in the values object array. The order in which the Binding elements appear under the MultiBinding element is the order in which those values are stored in the array.

 

Figure1: Important Classes hierarchy.

Figure2: Binding classes hierarchy

The XAML for the above mentioned logic is as follows.

<Window x:Class="DataConversion.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:mylocalXAMLnamespace="clr-namespace:DataConversion">
    <StackPanel>
        <StackPanel.Resources>
            <mylocalXAMLnamespace:AddConverter x:Key="XAMLResourceAddConverter" />
        </StackPanel.Resources>

        <TextBox Name="TextBox1" Text="10"></TextBox>
        <TextBox Name="TextBox2" Text="20"></TextBox>
        <Label Content="Sum of above two values:"></Label>
        <TextBox Name="textBox3">
            <TextBox.Text>
                <MultiBinding Converter="{StaticResource XAMLResourceAddConverter}">
                    <Binding ElementName="TextBox1" Path="Text"/>
                    <Binding ElementName="TextBox2" Path="Text"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>
</Window>

 

The MultiBinding tag takes binding as a parameter. See the following C# code that does the binding.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;

namespace DataConversion
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

    }

    public class AddConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            int result = Int32.Parse((string)values[0]) + Int32.Parse((string)values[1]);
            return result.ToString();
        }
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException("Cannot convert back");
        }
    }

}

 

You can specify multiple bindings in a MultiBinding object. When you use the MultiBinding object with a converter, it produces a final value for the binding target based on the values of those bindings. For example, color might be computed from red, blue, and green values, which can be values from the same or different binding source objects. When a value moves from the target to the sources, the target property value is translated to a set of values that are fed back into the bindings.

Download the Source Code from here

If it’s a good idea, go ahead and do it. It is much easier to apologize than it is to get permission. Admiral Grace Hopper

Data Binding–Source & Target

WPF Data Binding:

In data binding we establish a connection between the properties of two objects that are interested in binding. Binding means establishing a relationship or forming a bond between two entities. In this relationship, one object is referred to as the source and one object is referred to as the target. In the most typical scenario, your source object is the object that contains your data and your target object is a control that displays that data.

For instance, consider a Employee class with a EmployeeName property. If you want to show the EmployeeName property value in the TextBox UI and have the UI automatically change when the EmployeeName property value changes at run-time, you can bind the TextBox.Text property to the EmployeeName property of the Employee object as shown in the following figure 1.

image    Figure 1: Source & Target Objects in Binding

Download code from my article here.

ABCs of Data Binding

Building the presentation (User Interface) applications is all about displaying and manipulation of data. Well, WPF has a powerful feature to display data in UI controls that can be bound to the data present in our control (business) or entity (data) classes or any class data for that matter.

Suppose you have a class called person and it has a property  public string PersonName that you want to display in a text box. How do we bind these two objects together? Well, WPF’s DataBinding comes to the rescue. Each binding has these four components:

  • A binding target object
  • A target property
  • A binding source
  • A path to the value in the binding source to use.

For example,if you want to bind the content of a TextBox to the Name property of an employee object, your target object is the TextBox, the target property is the Text property, the value to use is EmployeeName, and the source object is the employee object. The following figure illustrates the concepts of DataBinding.

 

image

Figure 1: Components of DataBinding

Mode Property:

You use the Mode property to specify the direction of the binding, i.e. source -> target or target <- source. The following enumeration list shows the available options for binding

  • Default causes the default Mode value of target property to be used.
  • OneTime updates the target property only when the application starts or when the DataContext undergoes a change.
  • OneWay updates the target property only when the source property changes.
  • TwoWay updates the target property or the property whenever either the target property or the source property changes.
  • OneWayToSource updates the source property when the target property changes.

UpdateSourceTrigger Property:

The UpdateSourceTrigger property of the binding determines what triggers the update of the source. If you a bind a variable to a control, then the data from the control can be transferred to the variable by using this property.

  • Default: Any of the following values (Depends on the control)
  • Explicit:The Source Value Gets Updated when the appications calls UpdateSource
  • LostFocus: The Source Value Gets Updated when the UIElement control loses focus
  • PropertyChanged:The Source Value Gets Updated when the user types in the UIElement control

Following is the code of the employee class that exposes a property called EmployeeName that we want to bind to the textbox control. To make binding happen, the following should be implemented on the data class.

  1. Derive the class exposing the properties from INotifyPropertChanged.
  2. Declare the event. Ex: public event PropertyChangedEventHandler PropertyChanged;
  3. Call OnPropertyChanged nd pass the property name whenever the property is updated Ex: OnPropertyChanged("EmployeeName");
  4. Create the OnPropertyChanged method to raise the event. Ex:
            protected void OnPropertyChanged(string name)
            {
                PropertyChangedEventHandler handler = PropertyChanged;
                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));
                }
            }
Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Documents;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Navigation;
  13. using System.Windows.Shapes;
  14. using System.ComponentModel;
  15.  
  16. namespace Bindingtoclasses
  17. {
  18.     public partial class MainWindow : Window
  19.     {
  20.         public MainWindow()
  21.         {
  22.             InitializeComponent();
  23.             Employee P = new Employee("Hello World");
  24.             this.DataContext = P;
  25.         }
  26.     }
  27.  
  28.     // This class implements INotifyPropertyChanged to support one-way and two-way bindings
  29.     // (such that the UI element updates when the source has been changed dynamically)
  30.     public class Employee : INotifyPropertyChanged
  31.     {
  32.         private string name;
  33.         // Declare the event
  34.         public event PropertyChangedEventHandler PropertyChanged;
  35.  
  36.         public Employee()
  37.         {
  38.         }
  39.  
  40.         public Employee(string value)
  41.         {
  42.             this.name = value;
  43.         }
  44.  
  45.         public string EmployeeName
  46.         {
  47.             get { return name; }
  48.             set
  49.             {
  50.                 name = value;
  51.                 // Call OnPropertyChanged whenever the property is updated
  52.                OnPropertyChanged("EmployeeName");
  53.             }
  54.         }
  55.  
  56.         //// Create the OnPropertyChanged method to raise the event
  57.         protected void OnPropertyChanged(string name)
  58.         {
  59.             PropertyChangedEventHandler handler = PropertyChanged;
  60.             if (handler != null)
  61.             {
  62.                 handler(this, new PropertyChangedEventArgs(name));
  63.             }
  64.         }
  65.     }
  66.  
  67. }

The XAML code to bind the class property to the textbox controls is as follows. To make binding happen, the following should be implemented in the XAML code.

  1. First we need to create an object of the employee class in XAML in the parent element. Ex:
    <Grid.Resources>
            <src:Employee x:Key="myDataSource" EmployeeName="Kishore1021"/>
    </Grid.Resources>

  2. Instead of creating an object in XAML, we can also use DataContext property, create an employee object in the code and assign it to the DataContext as follows
            public MainWindow()
            {
                InitializeComponent();
                Employee P = new Employee("Hello World");
                this.DataContext = P;
            }

  3. I used both in the following sample . Line 16 and 17 uses the local object created in XAML and line 18 uses the DataContext and so directly uses the property name. More info on DataContext in the coming blogs.
  4. Use the Binding Markup Extension “{Binding}” and key in the parameters. In Line 16, I am binding the TextBox.Text to myDataSource object and in that object, I am binding to EmployeeName and the source gets updated when the property gets changed. So as you type, the text in textbox2 also gets changed.
  5. Line 17 also uses the same concept as above except that it doesn’t update the source as the user types. Since the default value of updateSourceTrigger binding property is LostFocus, the textbox1 gets updated only when textbox2 loses focus.
  6. Line 18 uses DataContext and so uses the EmployeeName property directly and binds to textbox3.
    Code Snippet
    1. <Window x:Class="Bindingtoclasses.MainWindow"
    2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
    4.         xmlns:src="clr-namespace:Bindingtoclasses"
    5.  
    6.         Title="MainWindow" Height="350" Width="525">
    7.     <Grid>
    8.         <Grid.Resources>
    9.                 <src:Employee x:Key="myDataSource" EmployeeName="Kishore1021"/>
    10.         </Grid.Resources>
    11.         <Grid.RowDefinitions>
    12.             <RowDefinition Height="*"></RowDefinition>
    13.             <RowDefinition Height="*"></RowDefinition>
    14.             <RowDefinition Height="*"></RowDefinition>
    15.         </Grid.RowDefinitions>
    16.         <TextBox Grid.Row="0" Text="{Binding Source={StaticResource myDataSource}, Path=EmployeeName, UpdateSourceTrigger=PropertyChanged}"/>
    17.         <TextBox Grid.Row="1" Text="{Binding Source= {StaticResource myDataSource}, Path=EmployeeName}"></TextBox>
    18.         <TextBox Grid.Row="2" Text="{Binding Path=EmployeeName}"></TextBox>
    19.         
    20.     </Grid>
    21. </Window>

The output of the program is as follows

image

Download code from Microsoft Skydrive :

Direct Link : https://skydrive.live.com/redir.aspx?cid=38ecce05b21b8b44&amp;resid=38ECCE05B21B8B44!394&amp;parid=38ECCE05B21B8B44!393

"If you’re riding ahead of the herd, take a look back every now and then to make sure it’s still there" – Will Rogers

DataContext in WPF

DataContext

DataContext is one of the most fundamental concepts in Data Binding. The Binding object needs to get its data from somewhere, and there are a few ways to specify the source of the data like using Source property directly in the Binding, inheriting a DataContext from the nearest element when traversing up in the tree, setting the ElementName and RelativeSource properties in the Binding object.

User interface elements in WPF have a DataContext dependency property. That property has the aforementioned "value inheritance" feature enabled, so if you set the DataContext on an element to a Student object, the DataContext property on all of its logical descendant elements will reference that Student object too. This means that all data bindings contained within that root element’s element tree will automatically bind against the Student object, unless explicitly told to bind against something else. This feature is extremely useful while designing WPF applications. In the following example, we are setting the DataContext in the code and all the elements in the window gets to access the Student object.

Exposing the entire object as DataContext from the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DataContextSample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Student objstudent = new Student();
            objstudent.StudentName = "Kishore1021";
            this.DataContext = objstudent;
        }

        public class Student
        {
            private string studentname;

            public string StudentName
            {
                get
                {
                    return studentname;
                }
                set
                {
                    studentname = value;
                }
            }

        }
    }
}

 
XAML for the above code
  1. <Window x:Class="DataContextSample.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         Title="MainWindow" Height="350" Width="525">
  5.     <Grid>
  6.         <Grid.RowDefinitions>
  7.             <RowDefinition Height="*"> </RowDefinition>
  8.         </Grid.RowDefinitions>
  9.         <TextBox Name="TextBox1" Text="{Binding Path=StudentName}"></TextBox>
  10.     </Grid>
  11. </Window>

 
Download the source code from Microsoft here
 

Exposing just a single property value from the code:

In the Student class, I added one more property Address. In the MainWindow, an Employee object is created and initialized with some values and we are setting just the address as the datacontext using this.DataContext = objstudent.Address; in line28

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Data;
  8. using System.Windows.Documents;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Navigation;
  13. using System.Windows.Shapes;
  14.  
  15. namespace DataContextSample
  16. {
  17.     /// <summary>
  18.     /// Interaction logic for MainWindow.xaml
  19.     /// </summary>
  20.     public partial class MainWindow : Window
  21.     {
  22.         public MainWindow()
  23.         {
  24.             InitializeComponent();
  25.             Student objstudent = new Student();
  26.             objstudent.StudentName = "Kishore1021";
  27.             objstudent.Address = "Washington DC";
  28.             this.DataContext = objstudent.Address;
  29.         }
  30.  
  31.         public class Student
  32.         {
  33.             private string studentname;
  34.             private string address;
  35.  
  36.             public string Address
  37.             {
  38.                 get { return address; }
  39.                 set { address = value; }
  40.             }
  41.  
  42.             public string StudentName
  43.             {
  44.                 get
  45.                 {
  46.                     return studentname;
  47.                 }
  48.                 set
  49.                 {
  50.                     studentname = value;
  51.                 }
  52.             }
  53.  
  54.  
  55.         }
  56.     }
  57. }

 

In the XAML code, created two textblocks and assigned the address. Keep a watch on how I am using the DataContext values. Since we are just setting the Address as DataContext, TextBlock1 binding doesn’t know where to find in that address property. TextBlock2 binds to whatever is there in the datacontext, which is just the address property..

  1. <Window x:Class="DataContextSample.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         Title="MainWindow" Height="350" Width="525">
  5.     <Grid>
  6.         <Grid.RowDefinitions>
  7.             <RowDefinition Height="*"> </RowDefinition>
  8.             <RowDefinition Height="*"></RowDefinition>
  9.         </Grid.RowDefinitions>
  10.         <TextBlock Grid.Row="0" Name="TextBlock1" Text="{Binding Path=Address}"></TextBlock>
  11.         <TextBlock Grid.Row="1" Name="TextBlock2" Text="{Binding Path=.}"></TextBlock>
  12.     </Grid>
  13. </Window>

 

Download the source code from here

To Understand the above concept better, see the following code. I have an employee class and one more class called AnotherClass and used employee class as a property inside that class. In the mainwondow class, we are creating an employee class object and initializing it with some values. Then we are creating an anotherclass object and initializing with the previously created employee object as well as one more property of anotherclass “State” and then we are assigning this anotherclass object as dataconext. There are several ways to specify the binding source object. Using the DataContext property on a parent element is useful when you are binding multiple properties to the same source. However, sometimes it may be more appropriate to specify the binding source on individual binding declarations.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Bindingtoclasses
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Employee P = new Employee("Hello World");
            P.State = "MD";
            AnotherClass c = new AnotherClass();
            c.EmployeeNameTest = P;
            c.AnotherField = "Another Value";
            this.DataContext = c;
        }
    }

    public class AnotherClass : INotifyPropertyChanged
    {

        private string anotherfield;
        private Employee emp;

        public string AnotherField
        {
            get { return anotherfield; }
            set
            {
                anotherfield = value;
                OnPropertyChanged("AnotherField");
            }
        }

        public Employee EmployeeNameTest
        {
            get { return emp; }
            set
            {
                emp = value;
                OnPropertyChanged("EmployeeNameTest");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        //// Create the OnPropertyChanged method to raise the event
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }

        public override string ToString()
        {
            return string.Format("My ToString implementation of AnotherClass");
        }

    }

    // This class implements INotifyPropertyChanged to support one-way and two-way bindings
    // (such that the UI element updates when the source has been changed dynamically)
    public class Employee : INotifyPropertyChanged
    {
        private string name;
        private string state;
        // Declare the event
        public event PropertyChangedEventHandler PropertyChanged;

        public Employee()
        {
        }

        public Employee(string value)
        {
            this.name = value;
        }

        public string EmployeeName
        {
            get { return name; }
            set
            {
                name = value;
                // Call OnPropertyChanged whenever the property is updated
               OnPropertyChanged("EmployeeName");
            }
        }

        public string State
        {
            get { return state; }
            set
            {
                state = value;
                OnPropertyChanged("State");
            }
        }

        //// Create the OnPropertyChanged method to raise the event
        protected void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

}

 

In the XAML: Even though we assigned the entire anotherclass object as datacontext, I am just assigning the EmployeeNameTest object in it as the datacontext for the grid using the code <Grid DataContext="{Binding Path=EmployeeNameTest}"> .

<Window x:Class="Bindingtoclasses.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:src="clr-namespace:Bindingtoclasses"

        Title="MainWindow" Height="350" Width="525">
    <Grid DataContext="{Binding Path=EmployeeNameTest}">
        <Grid.Resources>
                <src:Employee x:Key="myDataSource" EmployeeName="Kishore1021"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Name="TextBox1" Grid.Row="0" Text="{Binding Source={StaticResource myDataSource}, Path=EmployeeName, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Name="TextBox2" Grid.Row="1" Text="{Binding Source= {StaticResource myDataSource}, Path=EmployeeName}"></TextBox>
        <TextBox Name="TextBox3" Grid.Row="2" Text="{Binding Path=EmployeeName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        <TextBox Name="TextBox4" Grid.Row="3" Text="{Binding Path=EmployeeName}"></TextBox>
        <TextBlock Name="TextBlock1" Grid.Row="4" Text="{Binding Path=EmployeeName}"/>
        <TextBlock Name="TextBlock2" Grid.Row="5" Text="{Binding Path=AnotherField}"/>
        
    </Grid>
</Window>

 

Download the source code from here

 

Priority of Source VS DataContext:
Code Snippet
<Window x:Class="DataBinding_Source_Property.MainWindow"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
       Title="MainWindow" Height="350" Width="525"
       xmlns:kishore="clr-namespace:DataBinding_Source_Property">
   <Window.Resources>
       <kishore:Person x:Key="PersonXAMLDataSource" FullName="Kishore1021"/>
        <kishore:Person x:Key="Person1" FullName="Person1Name"/>
    </Window.Resources>
   
    <Grid DataContext="{StaticResource Person1}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"> </RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
       
        <TextBox Grid.Row="0" Text="{Binding Source={StaticResource PersonXAMLDataSource}, Path=FullName}"></TextBox>
        <TextBox Grid.Row="1" Text="{Binding Path=FullName}"/>
    </Grid>
</Window>

The first TextBox inherits the DataContext from the parent Grid as well as has a Source set in the Binding object too. In this case, Source takes priority, causing the TextBox to bind to the Name property of the resource with key “PersonXAMLDataSource” – this displays “kishore1021”. The second inherits the DataContext from the parent Grid causing the TextBox to bind to the Name property of the resource with key “Person1”, causing it to display “Person1Name”. WPF will search up the element tree until it encounters a DataContext object if a Source or RelativeSource is not used. Once it finds a non-null DataContext, that object is used for binding. Useful for binding several properties to the same object.

Most data bound applications tend to use DataContext much more heavily than Source. Use DataContext only when you need to bind more than one property to a particular source. When binding only one property to a source, always use Source. The reason for this is ease of debugging – We can see all the information about the Binding in one place than search for the nearest DataContext to understand what is going on. Other than setting the DataContext property on an element directly, inheriting the DataContext value from an ancestor , and explicitly specifying the binding source by setting the Source property on the Binding, you can also use the ElementName property or the RelativeSource property to specify the binding source. The ElementName property is useful when you are binding to other elements in your application, such as when you are using a slider to adjust the width of a button. The RelativeSource property is useful when the binding is specified in a ControlTemplate or a Style.

"We must be silent before we can listen. We must listen before we can learn. We must learn before we can prepare. We must prepare before we can serve. We must serve before we can lead." – William Arthur Ward

Binding Object Properties – Source

One of the splendid aspects of the WPF data binding engine is that it can bind to nearly any data source including XML data, ADO.NET classes, LINQ queries, WPF elements, and types that implement IEnumerable or IList. Source – references a Binding‘s data source. By default this object references the element’s DataContext value, which might be inherited from an ancestor element’s DataContext, as discussed in the DataContext section. If you set this property to a non-null value, then the data binding operation will treat that value as the place where data is pushed to and pulled from. A binding configured with the Source property takes precedence over any applied data context.

Ex of Source Objects:

  • You can bind to any CLR objects, including list objects. You can bind to the entire object or public properties, sub-properties, and indexers of the object. Fields are not supported. The binding engine uses CLR reflection to get the values of the properties. Alternatively, objects that implement ICustomTypeDescriptor or have a registered TypeDescriptionProvider also work with the binding engine.
  • You can bind to ADO.NET objects such as DataTable.
  • You can bind to an XmlNode, XmlDocument, or XmlElement, and run XPath queries on them.

As has been discussed earlier, every binding must have a binding target and target property. The binding isn’t complete unless you also specify the data source and source property.

Sometimes you want to show a single value from a data source. It might be showing a font name in a label or an invoice date in a calendar control. Perhaps you’d like to bind the value of one control to the input of another.  Here is an example showing how to bind the Value property of a Slider control to the FontSize property of a TextBlock:

<Slider x:Name='mSlider' Orientation='Horizontal' Minimum='10' Maximum='80' Value='25' />
        <TextBlock Text='Hello World' Margin='5,0' FontSize= '{Binding ElementName=mSlider, Path= Value}'/>
        
        

A binding source is usually a property on an object so you need to provide both the data source object and the data source property in your binding XAML. In the above example the ElementName attribute signifies that you want data from another element on the page and the Path signifies the appropriate property. A binding path can be a complex value, drilling into the member hierarchy, but in this case it’s just the name of the property.

What Can Be a Data Source?: You can use any type as a data source as long as it has a public parameter less constructor and at least one public property. Here’s a sample of binding to System.String. In the example below, we are creating a local resource in the XAML and using that as a Data Source in the binding to bind the TextBox to the local employee object we created in XAML. Coming to TextBlock, we are just saying Text=”{Binding}”, which is setting the textBlock binding in the XAML file and the data context in the code behind: So this TextBlock binds to the EmployeeName string property of the Employee class object we created in the code behind.

  1. <Window x:Class="Bindingtoclasses.MainWindow"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
  4.         xmlns:src="clr-namespace:Bindingtoclasses"
  5.         Title="MainWindow" Height="350" Width="525">
  6.     <Grid >
  7.         <Grid.Resources>
  8.                 <src:Employee x:Key="myDataSource" EmployeeName="Kishore1021"/>
  9.         </Grid.Resources>
  10.         <Grid.RowDefinitions>
  11.             <RowDefinition Height="*"></RowDefinition>
  12.             <RowDefinition Height="*"></RowDefinition>
  13.             <RowDefinition Height="*"></RowDefinition>
  14.             <RowDefinition Height="*"></RowDefinition>
  15.         </Grid.RowDefinitions>
  16.         <TextBox Grid.Row="0" Text="{Binding Source= {StaticResource myDataSource}, Path=EmployeeName}"></TextBox>
  17.         <TextBlock Grid.Row="1" Text="{Binding}"></TextBlock>
  18.             
  19.         </Grid>
  20. </Window>

 

In the C# code-behind file:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace Bindingtoclasses
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            Employee P = new Employee("Hello World");
            this.DataContext = P.EmployeeName;
        }
    }

    public class Employee
    {
        private string name;

        public Employee()
        {
        }

        public Employee(string value)
        {
            this.name = value;
        }

        public string EmployeeName
        {
            get { return name; }
            set
            {
                name = value;
            }
        }

    }

}

 

Source code can be downloaded from here.

There are many ways to specify your binding source, that is, to specify where your data is coming from. The simplest way is to instantiate the source object as a resource in XAML and then the Source property of the Binding to that resource

Using the Source property is simpler and more readable. However, if multiple properties bind to the same source, consider using the DataContext property. The DataContext property provides a convenient way to establish a data scope. Say you have many controls and you want all of them to bind to the same source.

<Window x:Class="Bindingtoclasses.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:src="clr-namespace:Bindingtoclasses"

        Title="MainWindow" Height="350" Width="525">
    <Grid DataContext="{Binding Path=.}">
        <Grid.Resources>
                <src:Employee x:Key="myDataSource" EmployeeName="Kishore1021"/>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Name="TextBox1" Grid.Row="0" Text="{Binding Source={StaticResource myDataSource}, Path=EmployeeName, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Name="TextBox2" Grid.Row="1" Text="{Binding Source= {StaticResource myDataSource}, Path=EmployeeName}"></TextBox>
        <TextBox Name="TextBox3" Grid.Row="2" Text="{Binding Path=EmployeeNameTest.EmployeeName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></TextBox>
        <TextBox Name="TextBox4" Grid.Row="3" Text="{Binding Path=EmployeeNameTest.EmployeeName}"></TextBox>
        <TextBlock Name="TextBlock1" Grid.Row="4" Text="{Binding Path=EmployeeNameTest.EmployeeName}"/>
        <TextBlock Name="TextBlock2" Grid.Row="5" Text="{Binding Path=AnotherField}"/>
        
    </Grid>
</Window>

In this case, you set the DataContext property of your Grid to that source so that all elements in that Grid inherit that common source. <Grid DataContext="{Binding Path=.}"> implies that whatever is the DataContext coming in from the code (In the code it is, this.DataContext = c)will be assigned to the grid. The TextBox3,4 and TextBlock1 in this example both inherit the binding source from the Grid . When you run this, you see TextBox3,4 and TextBlock1 with value “Hello World”.

Download the Source code from Microsoft here.

Priority of Source VS DataContext:
Code Snippet
<Window x:Class="DataBinding_Source_Property.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:kishore="clr-namespace:DataBinding_Source_Property">
   <Window.Resources>
       <kishore:Person x:Key="PersonXAMLDataSource" FullName="Kishore1021"/>
        <kishore:Person x:Key="Person1" FullName="Person1Name"/>
    </Window.Resources>
    
    <Grid DataContext="{StaticResource Person1}">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"> </RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        
        <TextBox Grid.Row="0" Text="{Binding Source={StaticResource PersonXAMLDataSource}, Path=FullName}"></TextBox>
        <TextBox Grid.Row="1" Text="{Binding Path=FullName}"/>
    </Grid>
</Window>

 

The first TextBox inherits the DataContext from the parent Grid and has a Source set in the Binding object too. In this case, the binding Source takes priority, causing the TextBox to bind to the Name property of the resource with key “PersonXAMLDataSource” – this displays “kishore1021”. The second inherits the DataContext from the parent Grid causing the TextBox to bind to the Name property of the resource with key “Person1”, causing it to display “Person1Name”.

Most data bound applications tend to use DataContext much more heavily than Source. Use DataContext only when you need to bind more than one property to a particular source. When binding only one property to a source, always use Source. The reason for this is ease of debugging – We can see all the information about the Binding in one place than search for the nearest DataContext to understand what is going on. In a small sample like the one above there is no big advantage, but in complex applications this could save you some time.

Download the source code from Microsoft here

"Management is efficiency in climbing the ladder of success; leadership determines whether the ladder is leaning against the right wall."— Stephen R. Covey

IValueConverter with Markup Extension

We have seen the Introduction to Value Converters in the previous post.  Converter is a Binding property of type IValueConverter. You can set this property to an instance of a class which implements that interface to intercept any movement of data from the binding source to the binding target, or vice versa. Value converters are very convenient and are used quite often.  If you want to use a normal ValueConverter in XAML, you have to add an instance of it to the resources and reference it by using a key. To learn more about instantiating an object as a resource in XAML, see the post. This is cumbersome, because and the key is typically just the name of the converter or you can derive your value converter from MarkupExtension and return its own instance in the ProvideValue override. So you can use it directly without referencing it from the resources.

public override object ProvideValue(IServiceProvider serviceProvider)
{
    throw new NotImplementedException();
}

So to enhance our experience with converters,  derive value converters from MarkupExtension. This way you can create and use it in the binding like this: Text={Binding studentname, Converter={x:MyConverter}}

Following are the steps to create a converter with Markup extension.

  1. Import namespace
    using System.Windows.Markup;

  2. Derive our class from MarkupExtension, IValueConverter
    public class ScoreToColorConverter : MarkupExtension, IValueConverter

  3. Override the ProvideValue method of MarkupExtension class and return this
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

  4. Implement the IValueConverter interface methods Convert & ConvertBack
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string s = (string) value;
        if (Int32.Parse(s) <= 35)
            return new SolidColorBrush(Colors.Red);
        else
            return new SolidColorBrush(Colors.Green);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

  5. Specify the xmlns:XXXX in the Window XAML tag
    xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"

  6. Specify the UI elements and mention the binding properties. Notice here that we are specifying the Binding converter property as Converter={MyXAMLClass:ScoreToColorConverter}, which is a simple and decent implementation.
    <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
     <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>

The complete XAML is:

<Window x:Class="DataBinding_MultiConverter2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="MainWindow" Height="350" Width="525"
        xmlns:MyXAMLClass="clr-namespace:DataBinding_MultiConverter2"
        >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Name="TB1" Text="90"></TextBox>
        <TextBox Grid.Row="1" Name="TB2" Background="{Binding ElementName=TB1, Path=Text, Converter={MyXAMLClass:ScoreToColorConverter}}"></TextBox>
    </Grid>
</Window>

The complete source code of the classes used is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Markup;

namespace DataBinding_MultiConverter2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class ScoreToColorConverter : MarkupExtension, IValueConverter
    {

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string s = (string) value;
            if (Int32.Parse(s) <= 35)
                return new SolidColorBrush(Colors.Red);
            else
                return new SolidColorBrush(Colors.Green);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Download the Source code from here. Default conversions may be available because of type converters that are present in the type being bound to. This behavior will depend on which type converters are available in the target. If in doubt, create your own converter.

Following are some typical scenarios where it makes sense to implement a data converter:

  • Your data should be displayed differently, depending on culture. For instance, you might want to implement a currency converter or a calendar date/time converter based on the values or standards used in a particular culture.

  • The data being used is not necessarily intended to change the text value of a property, but is instead intended to change some other value, such as the source for an image, or the color or style of the display text. Converters can be used in this instance by converting the binding of a property that might not seem to be appropriate, such as binding a text field to the Background property of a table cell.

  • More than one control or to multiple properties of controls are bound to the same data. In this case, the primary binding might just display the text, whereas other bindings handle specific display issues but still use the same binding as source information.

  • In the case of a MultiBinding, where a target property has a collection of bindings, you use a custom IMultiValueConverter to produce a final value from the values of the bindings. For example, color may be computed from red, blue, and green values, which can be values from the same or different binding source objects.

See Introduction to Value Converters in the previous post

Download the Source code from here

In organizations, real power and energy is generated through relationships. The patterns of relationships and the capacities to form them are more important than tasks, functions, roles, and positions. –Margaret Wheatley

Data Binding from the eyes of an VC++ developer

Having worked in VC++, MFC for more than a decade and getting to work on .NET WPF projects for a couple of years gave me an insight into the inner workings of data binding concepts in WPF.

Data binding in the user interface layer is nothing new. It has been around for quite some time, in various UI platforms, both for desktop and Web applications. The basic idea is that you "bind" the visual elements (controls) in a user interface to the data objects they are meant to display. The binding infrastructure then manages the data interactions from then on, so that modifications to the UI controls are reflected in the data objects, and vice versa. The major benefit of using data binding is that it reduces the amount of code the application developer needs to write.

Lets see how Data Binding is done in MFC:

In MFC, we have lot of great design concepts introduced like document/view, message mapping, dialog data routines and many more. DDX (Dialog Data Exchange) and DDV (Dialog Data Validation) are two great tools that allow us to easily set and access the values of MFC controls. DDX encapsulates the transfer of data between class member variables and dialog controls in a single place. Data Dialog Validation functions allow you to let Windows automatically restrict the values allowed within a control and is an easy way to validate data entry in the controls.

There are three main parts to DDX; UpdateData, DoDataExchange and the DDX-DDV functions (global functions) listed below from afxdd_.h.

  1. // simple text operations
  2. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, BYTE& value);
  3. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, short& value);
  4. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, int& value);
  5. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, UINT& value);
  6. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, long& value);
  7. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, DWORD& value);
  8. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, LONGLONG& value);
  9. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, ULONGLONG& value);
  10. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, CString& value);
  11. void AFXAPI DDX_Text(_Inout_ CDataExchange* pDX, _In_ int nIDC, _Out_z_cap_(nMaxLen) LPTSTR value, _In_ int nMaxLen);
  12. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, float& value);
  13. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, double& value);
  14. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, COleCurrency& value);
  15. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, COleDateTime& value);
  16. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, GUID& value);
  17. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, DECIMAL& value);
  18. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, FILETIME& value);
  19.  
  20. // special control types
  21. void AFXAPI DDX_Check(CDataExchange* pDX, int nIDC, int& value);
  22. void AFXAPI DDX_Radio(CDataExchange* pDX, int nIDC, int& value);
  23. void AFXAPI DDX_LBString(CDataExchange* pDX, int nIDC, CString& value);
  24. void AFXAPI DDX_CBString(CDataExchange* pDX, int nIDC, CString& value);
  25. void AFXAPI DDX_LBIndex(CDataExchange* pDX, int nIDC, int& index);
  26. void AFXAPI DDX_CBIndex(CDataExchange* pDX, int nIDC, int& index);
  27. void AFXAPI DDX_LBStringExact(CDataExchange* pDX, int nIDC, CString& value);
  28. void AFXAPI DDX_CBStringExact(CDataExchange* pDX, int nIDC, CString& value);
  29. void AFXAPI DDX_Scroll(CDataExchange* pDX, int nIDC, int& value);
  30. void AFXAPI DDX_Slider(CDataExchange* pDX, int nIDC, int& value);
  31.  
  32. void AFXAPI DDX_IPAddress(CDataExchange* pDX, int nIDC, DWORD& value);
  33.  
  34. void AFXAPI DDX_MonthCalCtrl(CDataExchange* pDX, int nIDC, CTime& value);
  35. void AFXAPI DDX_MonthCalCtrl(CDataExchange* pDX, int nIDC, COleDateTime& value);
  36. void AFXAPI DDX_MonthCalCtrl(CDataExchange* pDX, int nIDC, FILETIME& value);
  37. void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, CString& value);
  38. void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, CTime& value);
  39. void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, COleDateTime& value);
  40. void AFXAPI DDX_DateTimeCtrl(CDataExchange* pDX, int nIDC, FILETIME& value);
  41.  
  42. // for getting access to the actual controls
  43. void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl);
  44.  
  45. /////////////////////////////////////////////////////////////////////////////
  46. // Standard Dialog Data Validation routines
  47.  
  48. // range – value must be >= minVal and <= maxVal
  49. // NOTE: you will require casts for 'minVal' and 'maxVal' to use the
  50. //   UINT, DWORD or float types
  51. void AFXAPI DDV_MinMaxByte(CDataExchange* pDX, BYTE value, BYTE minVal, BYTE maxVal);
  52. void AFXAPI DDV_MinMaxShort(CDataExchange* pDX, short value, short minVal, short maxVal);
  53. void AFXAPI DDV_MinMaxInt(CDataExchange* pDX, int value, int minVal, int maxVal);
  54. void AFXAPI DDV_MinMaxLong(CDataExchange* pDX, long value, long minVal, long maxVal);
  55. void AFXAPI DDV_MinMaxUInt(CDataExchange* pDX, UINT value, UINT minVal, UINT maxVal);
  56. void AFXAPI DDV_MinMaxDWord(CDataExchange* pDX, DWORD value, DWORD minVal, DWORD maxVal);
  57. void AFXAPI DDV_MinMaxLongLong(CDataExchange* pDX, LONGLONG value, LONGLONG minVal, LONGLONG maxVal);
  58. void AFXAPI DDV_MinMaxULongLong(CDataExchange* pDX, ULONGLONG value, ULONGLONG minVal, ULONGLONG maxVal);
  59. void AFXAPI DDV_MinMaxFloat(CDataExchange* pDX, float const& value, float minVal, float maxVal);
  60. void AFXAPI DDV_MinMaxDouble(CDataExchange* pDX, double const& value, double minVal, double maxVal);
  61.  
  62. // special control types
  63. void AFXAPI DDV_MinMaxSlider(CDataExchange* pDX, DWORD value, DWORD minVal, DWORD maxVal);
  64. void AFXAPI DDV_MinMaxDateTime(CDataExchange* pDX, CTime& refValue, const CTime* refMinRange, const CTime* refMaxRange);
  65. void AFXAPI DDV_MinMaxDateTime(CDataExchange* pDX, COleDateTime& refValue, const COleDateTime* refMinRange, const COleDateTime* refMaxRange);
  66. void AFXAPI DDV_MinMaxMonth(CDataExchange* pDX,    CTime& refValue, const CTime* pMinRange, const CTime* pMaxRange);
  67. void AFXAPI DDV_MinMaxMonth(CDataExchange* pDX, COleDateTime& refValue, const COleDateTime* refMinRange, const COleDateTime* refMaxRange);
  68.  
  69.  
  70. // number of characters
  71. void AFXAPI DDV_MaxChars(CDataExchange* pDX, CString const& value, int nChars);
  72.  
  73. /////////////////////////////////////////////////////////////////////////////

 

 

The framework calls CWnd::DoDataExchange to exchange and validate dialog data.

protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

** Note that DoDataExchange is a virtual function.

You need to override this member function DoDataExchange if you wish to utilize the framework’s automatic data exchange and validation. An implementation of DoDataExchange is shown below. I added a control variable and a data variable of type string to an edit control whose ID is IDC_EDIT1 .

void CMfcSampleDialog::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_EDIT1, controlvar);
    DDX_Text(pDX, IDC_EDIT1, strvariable);
}

It’s to be noted that DoDataExchange is never called directly, it’s called by the CWnd::UpdateData member function found in afxwin.h. UpdateData sets up an object called a CDataExchange that holds information about the direction of the transfer and so on and passes this to DoDataExchange to do the work. The body of DoDataExchange is generally just a whole lot of DDX (and DDV) calls.

Following is the declaration of CWnd::UpdateData member function found in afxwin.h

// Dialog Data support
public:
    BOOL UpdateData(BOOL bSaveAndValidate = TRUE);

UpdateData is called to initialize data in a dialog box, or to retrieve and validate dialog data. The bSaveAndValidate flag indicates whether a dialog box is being initialized (set bSaveAndValidate = FALSE) or data is being retrieved (set bSaveAndValidate = TRUE). The framework automatically calls UpdateData with bSaveAndValidate set to FALSE when a modal dialog box is created in the default implementation of CDialog::OnInitDialog. The call occurs before the dialog box is visible. The default implementation of CDialog::OnOK calls this member function with bSaveAndValidate set to TRUE to retrieve the data, and if successful, will close the dialog box.

To validate data, for ex, if the edit box should allow only 10 chars, then the following validation routine takes care of it.

DDV_MaxChars(pDX, m_streditcontrolvariable, 10);

DataBinding in WPF:

WPF provides a simple and powerful way to auto-update data between the user-data  and the user interface. This mechanism is called DataBinding. Every time when the data of your class model changes, it automatically reflects the updates to the user interface and vice versa. This is similar to UpdateData in c++ and in WPF it’s related to bringing data to the user interface. Data binding in WPF is ubiquitous and seamless. It is so powerful and flexible that it literally forces you to change the way you think about designing and developing user interfaces. With one simple API you can bind to domain/business objects, XML data, visual elements, ADO.NET data containers, collections, and basically anything else you can think of. You can use value converters to execute arbitrary data manipulation operations when bound values are passed back and forth. You can perform data validation by creating custom validation rules and applying them to a binding. The list goes on. Data binding in WPF is really a huge step forward.

Binding is a markup extension. When you use the binding extension to declare a binding, the declaration consists of a series of clauses following the Binding keyword and separated by commas (,).

<TextBox Grid.Row="0" Text="{Binding Source={StaticResource myDataSource}, Path=PONumber, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Grid.Row="1" Text="{Binding Source= {StaticResource myDataSource}, Path=PONumber}"></TextBox>
<TextBox Grid.Row="2" Text="{Binding Path=PONumber}"></TextBox>

The clauses in the binding declaration can be in any order and there are many possible combinations. The clauses are Name=Value pairs where Name is the name of the Binding property and Value is the value you are setting for the property. Data binding can also mean that if an outer representation of the data in an element changes, then the underlying data can be automatically updated to reflect the change. For example, if the user edits the value in a TextBox element, the underlying data value is automatically updated to reflect that change.

When creating binding declaration strings in markup, they must be attached to the specific dependency property of a target object. The above example shows how to bind the TextBox.Text property using the binding extension, specifying the Source and Path properties.

The source of a databinding can be a normal .NET property or a DependencyProperty. The target property of the binding must be a DependencyProperty.

To make the databinding properly work, both sides of a binding must provide a change notification that tells the binding when to update the target value. On normal .NET properties this is done by raising the PropertyChanged event of the INotifyPropertyChanged interface. On DependencyProperties it is done by the PropertyChanged callback of the property metadata

 

  

image

As illustrated by the above figure, data binding is essentially the bridge between the binding target and the binding source. The figure demonstrates the following fundamental WPF data binding concepts:

  • Typically, each binding has these four components: a binding target object, a target property, a binding source, and a path to the value in the binding source to use. For example, if you want to bind the content of a TextBox to the Name property of an PurchaseOrders object, your target object is the TextBox, the target property is the Text property, the value to use is PONumber, and the source object is the PurchaseOrders object.

  • The target property must be a dependency property. Most UIElement properties are dependency properties and most dependency properties, except read-only ones, support data binding by default. (Only DependencyObject types can define dependency properties and all UIElements derive from DependencyObject.)

  • Although not specified in the figure, it should be noted that the binding source object is not restricted to being a custom CLR object. WPF data binding supports data in the form of CLR objects and XML. To provide some examples, your binding source may be a UIElement, any list object, a CLR object that is associated with ADO.NET data or Web Services, or an XmlNode that contains your XML data.

Direction of the Data Flow

Databinding can be unidirectional (source -> target or target <- source), or bidirectional (source <-> target). As mentioned previously and as indicated by the arrow in the figure above, the data flow of a binding can go from the binding target to the binding source (for example, the source value changes when a user edits the value of a TextBox) and/or from the binding source to the binding target (for example, your TextBox content gets updated with changes in the binding source) if the binding source provides the proper notifications.

You may want your application to enable users to change the data and propagate it back to the source object. Or you may not want to enable users to update the source data. You can control this by setting the Mode property of your Binding object.

  • OneWay binding causes changes to the source property to automatically update the target property, but changes to the target property are not propagated back to the source property. This type of binding is appropriate if the control being bound is implicitly read-only. For instance, you may bind to a source such as a stock ticker or perhaps your target property has no control interface provided for making changes, such as a data-bound background color of a table. If there is no need to monitor the changes of the target property, using the OneWay binding mode avoids the overhead of the TwoWay binding mode.

  • TwoWay binding causes changes to either the source property or the target property to automatically update the other. This type of binding is appropriate for editable forms or other fully-interactive UI scenarios. Most properties default to OneWay binding, but some dependency properties (typically properties of user-editable controls such as the Text property of TextBox and the IsChecked property of CheckBox) default to TwoWay binding. A programmatic way to determine whether a dependency property binds one-way or two-way by default is to get the property metadata of the property using GetMetadata and then check the Boolean value of the BindsTwoWayByDefault property.

  • OneWayToSource is the reverse of OneWay binding; it updates the source property when the target property changes. One example scenario is if you only need to re-evaluate the source value from the UI.

  • OneTime binding, which causes the source property to initialize the target property, but subsequent changes do not propagate. This means that if the data context undergoes a change or the object in the data context changes, then the change is not reflected in the target property. This type of binding is appropriate if you are using data where either a snapshot of the current state is appropriate to use or the data is truly static. This type of binding is also useful if you want to initialize your target property with some value from a source property and the data context is not known in advance. This is essentially a simpler form of OneWay binding that provides better performance in cases where the source value does not change.

You use the Mode property to specify the direction of the binding. The following enumeration list shows the available options for binding updates (to be precise):

  • TwoWay updates the target property or the property whenever either the target property or the source property changes.

  • OneWay updates the target property only when the source property changes.

  • OneTime updates the target property only when the application starts or when the DataContext undergoes a change.

  • OneWayToSource updates the source property when the target property changes.

  • Default causes the default Mode value of target property to be used.

Note that to detect source changes (applicable to OneWay and TwoWay bindings), the source must implement a suitable property change notification mechanism such as INotifyPropertyChanged. To implement INotifyPropertyChanged you need to declare the PropertyChanged event and create the OnPropertyChanged method. Then for each property you want change notifications for, you call OnPropertyChanged whenever the property is updated.

What Triggers Source Updates

Bindings that are TwoWay or OneWayToSource listen for changes in the target property and propagate them back to the source. This is known as updating the source. For example, you may edit the text of a TextBox to change the underlying source value. As described in the last section, the direction of the data flow is determined by the value of the Mode property of the binding.

However, does your source value get updated while you are editing the text or after you finish editing the text and point your mouse away from the TextBox? The UpdateSourceTrigger property of the binding determines what triggers the update of the source. If the UpdateSourceTrigger value is PropertyChanged, then the value pointed to by the right arrow of TwoWay or the OneWayToSource bindings gets updated as soon as the target property changes. However, if the UpdateSourceTrigger value is LostFocus, then that value only gets updated with the new value when the target property loses focus.

Similar to the Mode property, different dependency properties have different default UpdateSourceTrigger values. The default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus. This means that source updates usually happen whenever the target property changes, which is fine for CheckBoxes and other simple controls. However, for text fields, updating after every keystroke can diminish performance and it denies the user the usual opportunity to backspace and fix typing errors before committing to the new value. That is why the Text property has a default value of LostFocus instead of PropertyChanged.

 

UpdateSourceTrigger value

When the Source Value Gets Updated

Example Scenario for TextBox

LostFocus (default for TextBox.Text)

When the TextBox control loses focus

A TextBox that is associated with validation logic

PropertyChanged

As you type into the TextBox

TextBox controls in a chat room window

Explicit

When the application calls UpdateSource

TextBox controls in an editable form (updates the source values only when the user clicks the submit button)

 

Databinding is typically done in XAML by using the {Binding} markup extension. The following example shows a simple binding between the text of a TextBox and a property of a class:

Download code from Microsoft Skydrive

Lead and inspire people. Don’t try to manage and manipulate people. Inventories can be managed but people must be lead. –Ross Perot