WPF FAQ - DataBinding

What are the uses of BindingModes?

The most common binding scenarios involve the data getting updated from the source to the target. But, in some cases, the source has to be updated when changes are made by the users in the target. Such cases can be defined using the ‘BindingModes’ of the Binding markup extension class. ‘BindingModes’ is an enumeration property and it takes the following values.

1. OneWay – The target is updated whenever the source is updated.

2. TwoWay – A change to either the target or source updates the other.

3. OneWayToSource – It is an opposite of OneWay. The source is updated whenever the target value changes.

4. OneTime – It is similar to OneWay except that the changes to the source are also not reflected in the target. The target contains the value of the source when Binding was initiated.

Permalink
What is DataContext ? How is it used ?

Every FrameworkElement can be associated with a DataContext which will be used as the default data source during binding, if no other data source is specified in the binding code. Also, the children of this FrameworkElement auotmatically inherit this setting. This helps having to repeatedly specify this data source as the source of a binding, thereby letting you simplify the binding code.

The following code snippet is an example of implicit datasource using DataContext.

[XAML]

<StackPanel x:Name='Class' DataContext='{StaticResource student}'>
<Label x:Name='studcount' Content='{Binding Path=Count}'/>
<ListBox x:Name='Studname' DisplayMemberPath='Name' ItemsSource='{Binding}'/>
</StackPanel>
Permalink
How do I specify a HierarchicalDataTemplate for a templated type?

Sometimes you might have to specify a HierarchicalDataTemplate for a templated type. If so, you can only do this in code-behind. (If you have to do this in XAML try wrapping that template type within a non-templated dummy type.)

For example, if you have to do something like this:

            <HierarchicalDataTemplate ItemsSource='{Binding}'  
                                      DataType='{x:Type local:MyTemplatedList<int>}'>   
                <TextBlock Text='{Binding Name}'></TextBlock>  
            </HierarchicalDataTemplate>

The above wouldn’t compile because the XAML compiler doesn’t support this.

So, you will have to do this in code-behind instead:

using MyListType = MyTemplatedList<int>;

// Then in Window’s constructor for example:
HierarchicalDataTemplate hdt = new HierarchicalDataTemplate(typeof(MyListType));   
hdt.ItemsSource = new Binding();   
FrameworkElementFactory tb = new FrameworkElementFactory(typeof(TextBlock));   
tb.SetBinding(TextBlock.TextProperty, new Binding('Name'));   
hdt.VisualTree = tb;   
this.Resources[new DataTemplateKey(typeof(CountryList))] = hdt;  
</int>

Note that the above code also illustrates how to add a HierarchicalDataTemplate resource to the Resources list without specifying a key.

Permalink
How do I debug my data-binding setup?

XAML code is not debuggable and any bindings that are setup in XAML or in code-behind are normally very tricky to debug as well. This article provides some ideas on how to setup debugging to get error information and such when binding happens:

How can I debug WPF bindings

Permalink
How do I bind to a dictionary including the ability to get notifications when items are added or removed?

Dictionaries are very easy to work with in code and are useful in variety of scenarios. Being able to bind to it along with the ability to get notifications when items get added or removed is a very useful capability. This article provides you an ObservableDictionary that does the same:

Dr.WPF: Can I bind my ItemsControl to a dictionary?

Permalink
How do I apply custom sorting to the order of the items in a bound listbox?

To specify custom sorting using a custom implementation of an IComparer, you will have to use a CollectionViewSource, get it’s default view and set it’s CustomSort property as follows:

Sample ListBox bound to a CollectionViewSource:

<Window x:Class='WindowsApplication1.Window1'
    xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'
    xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
    xmlns:scm='clr-namespace:System.ComponentModel;assembly=windowsbase'
>
  <Window.Resources>
    <XmlDataProvider x:Key='list' >
      <x:XData>
        <Items xmlns=''>
          <Item>
            <Name>David</Name>
            <Age>20</Age>
          </Item>
          <Item>
            <Name>Marcus</Name>
            <Age>25</Age>
          </Item>
          <Item>
            <Name>George</Name>
            <Age>25</Age>
          </Item>
          <Item>
            <Name><![CDATA[Peter&#M]]></Name>
            <Age>25</Age>
          </Item>
        </Items>
      </x:XData>
    </XmlDataProvider>
    <CollectionViewSource
        Source='{Binding Source={StaticResource list}, XPath=Items/Item/Name}'
        x:Key='data'/>
  </Window.Resources>
  <ListBox
      Name='lb1'
      DisplayMemberPath='Name'
      ItemsSource='{Binding Source={StaticResource data}}'/>
</Window>

Then in code-behind specify the custom comparer as follows:

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
        this.lb1.Loaded += delegate
        {
            CollectionViewSource cvs = this.TryFindResource('data') as CollectionViewSource;
            if (cvs != null)
            {
                ListCollectionView view = cvs.View as ListCollectionView;
                if (view != null)
                {
                    view.CustomSort = new XmlComparer();
                }
            }
        };
    }

    public class XmlComparer : IComparer
    {
        public Int32 Compare(Object x, Object y)
        {
            XmlElement a = x as XmlElement;
            XmlElement b = y as XmlElement;
            if (a != null && b != null)
            {
                return String.Compare(a.InnerText, b.InnerText);
            }

            return -1;
        }
    }
}
Permalink
How can I bind a method and pass a parameter to the method ?

As with support for parameterized constructor, this is most useful for existing classes that are not databinding-friendly and can’t be changed. For your own types, you might as well expose potential datasources as properties. But note that the photos collection exposed a method call ‘GetFolderName’, that returned a string representing the folder containing all the current items. You could expose this method as a datasource as follows.

[XAML}

<ObjctDataProvider x:Key='dataProvider' ObjectType='{x:Type Local:Photos}' MethodName='GetFolderName'/>

If the parameters need to be passed to the method, you can use ObjectDataProvider’s ‘MethodParameters’ property ( which works just like it’s ConstructorParameter property).

To Bind this method, simply bind it to the entire ObjectDataProvider.

[XAML]

<TextBlock Text='{Binding source={StaticResource dataProvider}}'/>

Specifying the path in this case would apply to the instance returned by the method.

Permalink
How does TwoWay BindingMode work in an XMLDataProvider?

When TwoWay BindingMode is used, the XMLDataProvider writes the data to the ‘in – memory’ XML file and it does not write to the file in your hard disk. You have to perform your own serialization to write the data updated to the XML file in the hard disk.

Permalink
What is the use of the RelativeSource property ?

The ‘RelativeSource’ property of the Binding class is used to bind the data from an element by it’s relationship to the source element. RelativeSource is also a markup extension of type RelativeSource.

The following are some of the ways that RelativeSource can be used.

1. When the source element is equal to the target element,

[C#]

{Binding RelativeSource={RelativeSource Self}}

2. When the source element is equal to the target element’s TemplatedParent,

[C#]

{Binding RelativeSource={RelativeSource TemplatedParent}}

3. When the source element is equal to the closest parent of a given type,

[C#]

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type StackPanel}}, Path=Orientation}

4. When the source element is equal to the nth closest parent of a given type,

[C#]

{Binding RelativeSource={RelativeSource FindAncestor,AncestorLevel=1, AncestorType={x:Type Window}}, Path=Title}

5. When the source element is equal to the previous data item in a data – bound collection.

[C#]

{Binding RelativeSource={RelativeSource PreviousData}}
Permalink
How to Get or Set a value that indicates whether to include the DataErrorValidationRule ?

Setting this property provides an alternative to use the DataErrorValidationRule element, explicitly. The DataErrorValidationRule is a built-in validation rule that checks for errors that are raised by the ‘IDataErrorInfo’ implementation of the source object. If an error is raised, the binding engine creates a ValidationError with the error and adds it to the ‘Validation.Errors’ collection of the bound element. The lack of an error clears this validation feedback, unless another rule raises a validation issue.

This example shows how to implement validation logic on a custom object and then bind to it.

You can provide validation logic on the business layer if your source object implements IDataErrorInfo, as in the following example. In the following example, the ‘text’ property of the textbox binds to the ‘Age’ property of the Person object which has been made available for binding through a resource declaration that is given in the x:Keydata. The ‘DataErrorValidationRule’ checks for the validation errors raised by the IDataErrorInfo implementation.

[XAML]

<TextBox Style='{StaticResource textBoxInError}'>
    <TextBox.Text>
        <!--By setting ValidatesOnExceptions to True, it checks for exceptions
        that are thrown during the update of the source property.
        An alternative syntax is to add <ExceptionValidationRule/> within
        the <Binding.ValidationRules> section.-->
        <Binding Path='Age' Source='{StaticResource data}'
                 ValidatesOnExceptions='True'
                 UpdateSourceTrigger='PropertyChanged'>
            <Binding.ValidationRules>
                <!--DataErrorValidationRule checks for validation 
                    errors raised by the IDataErrorInfo object.-->
                <!--Alternatively, you can set ValidationOnDataErrors='True' on the Binding.-->
                <DataErrorValidationRule/>
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>
Permalink
How to pass a parameter to a function using ObjectDataProvider ?

A parameter can be passed to a function using the ‘MethodParameters’ of the ‘ObjectDataProvider’ class.

The following XAML code snippet demonstrates how to pass parameters to a function using an ObjectDataProvider.

[XAML]

<ObjectDataProvider ObjectInstance='{StaticResource odp1}' MethodName='WeightOnPlanet' x:Key='odp2?>
<ObjectDataProvider.MethodParameters>
<system:Double>95</system:Double>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
Permalink
How do I update the source as I type in a TextBox?

The source can be updated using the ‘UpdateSourceTrigger’ property of the TextBox. By default, the ‘UpdateSourceTrigger’ property is set to ’LostFocus’, i.e. the source is updated when the data-bound TextBox loses the focus. By setting the ‘UpdateSourceTrigger’ property to ’PropertyChanged’, the source will be updated as you type in a TextBox.

In the following code snippet a TextBox’s ‘Text’ property is bound with the Button’s ‘Width’ property. On changing the Text in the TextBox, the Width of the Button is updated.

[XAML]

<Button Name='hellobtn' Content='Hello' Width='150' Height='30'/>
<TextBox Text='{Binding ElementName=hellobtn, Path=Width, Height='20' UpdateSourceTrigger=PropertyChanged}'/>
Permalink
Can ItemsControl’s Items and ItemsSource properties be modified simultaneously ?

ItemControl’s items and ItemsSource can’t be modified simultaneously. ItemControl’s ‘Items’ property is used to add items manually and ‘ItemsSource’ property is used to bind the ItemControl with the datasource. You must not mix these techniques, simply for the reason that ItemsSource can only be set when there are no items in the Item collection and Items can only be set when the ItemsSource is set to null. Otherwise you’ll get an ‘InvalidOperation’ Exception. Note that regardless of which method you use to set items in an ItemControl, you can always retrieve items using the ItemsCollection.

Permalink
How to pass a parameter to a constructor using ObjectDataProvider ?

ObjectDataProvider provides the ability to pass the parameters to the constructors using the ‘ConstructorParameters’ property.

The following code snippet demonstrates how to pass parameters to a constructor.

[XAML]

<ObjectDataProvider ObjectType='{x:Type local:odpsource}' x:Key='obj1?>
<ObjectDataProvider.ConstructorParameters>
<system:Double>2000</system:Double>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
Permalink
In what way is an ObjectDataProvider useful?

ObjectDataProvider is a class that wraps your source object to provide some extra functionality.

The following are the distinguishing capabilities of ObjectDataProvider.

  • Passing parameters to the constructor.

  • Binding to a method (with or without parameters).

  • Replacing the source object.

  • Creating the source object asynchronously.

Permalink
When an XMLDataProvider can be used ? What are it’s specific uses ?

An XMLDataProvider can be used when your datasource is an XML file.

The following are some of the uses of XMLDataProvider.

  • XML can be pre-filtered using the XPath query of the XMLDataProvider.

  • It automatically reads the XML using a background thread without blocking the UI.

  • Data can be shared among the several controls.

  • If your XML uses Namespaces, then it is the convenient place to assign the XMLNamespaceManager.

Permalink