Tag Archives: XmlElement

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.

Advertisements

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

Binding Object Properties – UpdateSourceTrigger

Download the Source Code here.

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 mode section, the direction of the data flow is determined by the value of the Mode property of the binding. In the following sample, TextBox1 has UpdateSourceTrigger property set to PropertyChanged, so as the user starts editing the text in this control, it automatically updates the source and so the textbox2 also gets updated.

<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=EmployeeName}">
        <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>
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding Source={StaticResource myDataSource}, Path=EmployeeName, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Grid.Row="1" Text="{Binding Source= {StaticResource myDataSource}, Path=EmployeeName}"></TextBox>
        <TextBox Grid.Row="2" Text="{Binding Path=.}"></TextBox>
        <TextBlock Grid.Row="3" Text="{Binding}"></TextBlock>
        </Grid>
</Window>

 

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? See the attached source code and run the exe. The UpdateSourceTrigger property of the binding determines what triggers the update of the source. The dots of the right arrows in the following figure illustrate the role of the UpdateSourceTrigger property:

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)

Download the Source Code here.

"I don’t know the key to success, but the key to failure is trying to please everybody" – Bill Cosby

Binding Object Properties – Mode

The binding mode sets in which direction data will flow. Data usually flows from the source to the destination. There are five data binding modes.

Mode Description Direction of Flow
OneWayToSource From destination to source .
OneWay From source to destination.
OneTime The property is initially set, but updates to the source are not copied to the destination.
TwoWay Changes to source and destination are copied to each other.
Default Depends on the UI control.  

The default Mode varies between one-way and two-way depending on the dependency property that is being bound. You can always declare the binding mode explicitly to ensure that your binding has the desired behavior. In general, user-editable control properties, such as TextBox.Text and RangeBase.Value, default to two-way bindings, whereas most other properties default to one-way bindings.

The following code explains the concepts in details.

<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;
        Title="MainWindow" Height="350" Width="525">
    <Grid >
        <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 Path=EmployeeNameTest.EmployeeName, Mode=TwoWay}"/>
        <TextBox Name="TextBox2" Grid.Row="1" Text="{Binding Path=EmployeeNameTest.EmployeeName, Mode=OneWayToSource}"></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, Mode=OneWay}"></TextBox>
        <TextBlock Name="TextBlock1" Grid.Row="4" Text="{Binding Path=EmployeeNameTest.EmployeeName, Mode=OneTime}"/>
        <TextBlock Name="TextBlock2" Grid.Row="5" Text="{Binding Path=AnotherField, Mode=TwoWay}"/>
        
    </Grid>
</Window>

  • TextBox1 binds TwoWay, so it updates the source whenever the content changes as well as it gets updated when the source is changed (for ex, from TextBox2. It updates the source when the control loses focus.
  • TextBox2 binds OneWayToSource, so it gets populated once and this textbox never gets updated when the source changes. When the user types in the textbox, it updates the source with the value that it holds.
  • TextBox3 binds TwoWay, so it updates the source whenever the content changes as well as it gets updated when the source is changed . The difference between TextBox1 & TextBox3 is that, TextBox1 gets updates the source when the control loses focus and TextBox3 updates the source as the user types in because of UpdateSourceTrigger.
  • TextBox3 binds OneWay so it never updates the source. The data moves from source to target. So when the source is changed in any way, this control gets updated.

Download the source code from here.

"The older I get the less I listen to what people say and the more I look at what they do."— Andrew Carnegie