0% found this document useful (0 votes)
63 views

Data Binding

The document discusses data binding in XAML and WPF. It covers element to element binding using ElementName, data context, the components of a binding including target, target property, source and path, and how to create bindings. It also discusses data conversion, binding to collections using ItemsSource, using collection views to sort, filter and group data bound to an ItemsControl, and how to create a collection view by setting the Source property of a CollectionViewSource.

Uploaded by

yuvalp
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views

Data Binding

The document discusses data binding in XAML and WPF. It covers element to element binding using ElementName, data context, the components of a binding including target, target property, source and path, and how to create bindings. It also discusses data conversion, binding to collections using ItemsSource, using collection views to sort, filter and group data bound to an ItemsControl, and how to create a collection view by setting the Source property of a CollectionViewSource.

Uploaded by

yuvalp
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

Data Binding

Element to element binding

<TextBlock Text="This is a sizing text"


FontSize="{Binding Value, ElementName=_slider}"
TextAlignment="Center"
VerticalAlignment="Center" />
<Slider x:Name="_slider"
Grid.Row="1"
Minimum="10"
Maximum="80"
Value="30" />

Data Context
When data binding is declared on XAML elements, they resolve data binding by looking at their
immediate DataContext property. The data context is typically the binding source object for the binding source value
path evaluation.

Target = View Source = Model

Typically, each binding has four components:

o A binding target object.


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

For example, if you bound the content of a TextBox to the Employee.Name property, you would
set up your binding like the following table:

Setting Value
Target TextBox
Target property Text
Source object Employee

Source object value path Name

 The target property must be a dependency property.


 To establish a binding, you use the Binding object. The rest of this article discusses many of the
concepts associated with and some of the properties and usage of the Binding object.
The Binding.UpdateSourceTrigger property determines what triggers the update of the source.
The dots of the right arrows in the following figure illustrate the role of
the Binding.UpdateSourceTrigger property.

If the UpdateSourceTrigger value is UpdateSourceTrigger.PropertyChanged, then the value


pointed to by the right arrow of TwoWay or the OneWayToSource bindings is updated as
soon as the target property changes.

However, if the UpdateSourceTrigger value is LostFocus, then that value only is updated with
the new value when the target property loses focus.
6.1 Create a binding

To restate some of the concepts discussed in the previous sections, you establish a binding
using the Binding object, and each binding usually has four components: a binding target, a
target property, a binding source, and a path to the source value to use. This section discusses
how to set up a binding.

Binding sources are tied to the active DataContext for the element. Elements automatically
inherit their DataContext if they've not explicitly defined one.

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SDKSample">
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<DockPanel.DataContext>
<Binding Source="{StaticResource myDataSource}"/>
</DockPanel.DataContext>
<Button Background="{Binding Path=ColorName}"
Width="150" Height="30">
I am bound to be RED!
</Button>
</DockPanel>
6.2 Specifying the binding source

There are several ways to specify the binding source object

1. Using the DataContext property on a parent element is useful when you're binding multiple properties to the
same source The Parent : The dock panel defines its DataContext, say, Binding Object. In this example the
button sits inside the dock panel. It therefore inhertis its parent’s dataContext.

2. Inside an element
However, sometimes it may be more appropriate to specify the binding source on individual binding
declarations. For the previous example, instead of using the DataContext property, you can specify the
binding source by setting the Binding.Source property directly on the binding declaration of the
button, as in the following example.

<DockPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="clr-namespace:SDKSample">
<DockPanel.Resources>
<c:MyData x:Key="myDataSource"/>
</DockPanel.Resources>
<Button Background="{Binding Source={StaticResource myDataSource}, Path=ColorName}"
Width="150" Height="30">
I am bound to be RED!
</Button>
</DockPanel>

3. you can also use the Binding.ElementName property . The ElementName property is useful when you're
binding to other elements in your app, such as when you're using a slider to adjust the width of a button.
4. The RelativeSource property is useful when the binding is specified in a ControlTemplate or a Style. For
more information, see Binding sources overview.
6.3 Specifying the path to the value

If you want to bind to an entire object, the value to use would be the same as the binding source object. In
those cases, it's applicable to not specify a Path. Consider the following example.

<ListBox ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="true"/>

The above example uses the empty binding syntax: {Binding}. In this case, the ListBox inherits the DataContext from a
parent DockPanel element (not shown in this example). When the path isn't specified, the default is to bind to the
entire object. In other words, in this example, the path has been left out because we are binding
the ItemsSource property to the entire object. (See the Binding to collections section for an in-depth discussion.)

Binding and BindingExpression


Before getting into other features and usages of data binding, it's useful to introduce
the BindingExpression class. As you have seen in previous sections, the Binding class is the high-level class for
the declaration of a binding; it provides many properties that allow you to specify the characteristics of a
binding. A related class, BindingExpression, is the underlying object that maintains the connection between the
source and the target. A binding contains all the information that can be shared across several binding
expressions. A BindingExpression is an instance expression that cannot be shared and contains all the instance
information of the Binding.

Consider the following example, where myDataObject is an instance of the MyData class, myBinding is
the source Binding object, and MyData is a defined class that contains a string property
named ColorName. This example binds the text content of myText, an instance of TextBlock,
to ColorName.

// Make a new source


var myDataObject = new MyData();
var myBinding = new Binding("ColorName")
{
Source = myDataObject
};

// Bind the data source to the TextBox control's Text dependency property
myText.SetBinding(TextBlock.TextProperty, myBinding);

6.4 Data conversion

In the Create a binding section, the button is red because its Background property is bound to
a string property with the value "Red". This string value works because a type converter is
present on the Brush type to convert the string value to a Brush.

Adding this information to the figure in the Create a binding section looks like this.
[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color color = (Color)value;
return new SolidColorBrush(color);
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}

6.5 Binding to collections


Fortunately, our basic diagram still applies. If you're binding an ItemsControl to a collection, the
diagram looks like this.

As shown in this diagram, to bind an ItemsControl to a collection


object, ItemsControl.ItemsSource property is the property to use. You can think of ItemsSource as the
content of the ItemsControl. The binding is OneWay because the ItemsSource property
supports OneWay binding by default.

6.6 Collection views to Sort, Filter or Group

Once your ItemsControl is bound to a data collection, you may want to sort, filter, or group
the data. To do that, you use collection views, which are classes that implement
the ICollectionView interface.

If the source collection implements the INotifyCollectionChanged interface, the changes


raised by the CollectionChanged event are propagated to the views.

Because views do not change the underlying source collections, each source collection can
have multiple views associated with it. For example, you may have a collection of Task objects.
With the use of views, you can display that same data in different ways. For example, on the
left side of your page you may want to show tasks sorted by priority, and on the right side,
grouped by area.

6.7 How to create a view

1. We create the data in the app.cs. public ObservableCollection<AuctionItem> AuctionItems { get; set; } = new
ObservableCollection<AuctionItem>();
AuctionItems.Add(camera);
AuctionItems.Add(snowBoard);
AuctionItems.Add(insideCSharp);
AuctionItems.Add(laptop);
AuctionItems.Add(setOfChairs);
AuctionItems.Add(myDvdCollection);
AuctionItems.Add(tvDrama);
AuctionItems.Add(squashRacket);

2. We bind the data in the xaml:


<CollectionViewSource
Source="{Binding Source={x:Static Application.Current}, Path=AuctionItems}"
x:Key="ListingDataView" />

We use the CollectionViewSource

<ListBox Name="Master" AutomationProperties.Name="Items For Sale" Grid.Row="2" Grid.ColumnSpan="3" Margin="8"


ItemsSource="{Binding Source={StaticResource ListingDataView}}"
ItemContainerStyle="{StaticResource AuctionItemContainerStyle}"
AutomationProperties.LiveSetting="Assertive">
<ListBox.GroupStyle>
<GroupStyle
HeaderTemplate="{StaticResource GroupingHeaderTemplate}" />
</ListBox.GroupStyle>
</ListBox>

6.8 Sorting
As mentioned before, views can apply a sort order to a collection. As it exists in the underlying collection, your data may or
may not have a relevant, inherent order. The view over the collection allows you to impose an order, or change the default
order, based on comparison criteria that you supply. Because it's a client-based view of the data, a common scenario is that
the user might want to sort columns of tabular data per the value that the column corresponds to. Using views, this user-
driven sort can be applied, again without making any changes to the underlying collection or even having to requery for the
collection content. For an example, see Sort a GridView column when a header is clicked (.NET Framework).

The following example shows the sorting logic of the "Sort by category and date" CheckBox of the app
UI in the What is data binding section.

private void AddSortCheckBox_Checked(object sender, RoutedEventArgs e)


{
// Sort the items first by Category and then by StartDate
listingDataView.SortDescriptions.Add(new SortDescription("Category", ListSortDirection.Ascending));
listingDataView.SortDescriptions.Add(new SortDescription("StartDate", ListSortDirection.Ascending));
}
7.0 Data templates

<Window.Resources>
<DataTemplate x:Key="personTemplate">
<Border BorderBrush="Green"
BorderThickness="10">
<StackPanel Margin="4">
<TextBlock Foreground="Red"
FontSize="20"
Text="{Binding Name}"
TextAlignment="Center" />
<TextBlock Foreground="Black"
FontSize="16"
Text="{Binding Age}"
TextAlignment="Right" />
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="150" />
<RowDefinition Height="150" />
<RowDefinition Height="150" />
</Grid.RowDefinitions>

<ListBox Grid.Row="0"
x:Name="_list"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource personTemplate}" />
To see the changes in the view, a class entity like Person has to implement :
class Person : InotifyPropertyChanged

{
public string Name { get; set; }
public int Age { get; set; }

public event PropertyChangedEventHandler PropertyChanged;


}

To see changes in a collection in the view the collection has to inherent from ObservableCollection

DataContext = new Person { Age = 10, Name = "Bart" };


_list.ItemsSource = new ObservableCollection<Person> {
new Person { Name = "Bart", Age = 10 },
new Person { Name = "Homer", Age = 45 },
new Person { Name = "Marge", Age = 35 }
};

1. When a ui element declares it content: {Binding} it attaches itself to the DataContext


<Button Content="{Binding}" ContentTemplate="{StaticResource personTemplate}" />

2. When a list declares ItemTemplate, it attaches itself to an item template


To declare visibility. The data is prepared and attached in the controller.

<ListBox Grid.Row="1" x:Name="_list" HorizontalContentAlignment="Stretch"


ItemTemplate="{StaticResource personTemplate}" />
3. The template is declared elesewhere:
<Window.Resources>
<DataTemplate x:Key="personTemplate">
<Border BorderBrush="Green" BorderThickness="2">
<StackPanel Margin="4">
<TextBlock Foreground="Red" FontSize="20" Text="{Binding Name}"
TextAlignment="Center" />
<TextBlock Foreground="Black" FontSize="16" Text="{Binding Age}"
TextAlignment="Right" />
</StackPanel>
</Border>
</DataTemplate>
</Window.Resources>
7.1 Data Triggers
<DataTemplate>
<Border x:Name="_border" Margin="4" BorderBrush="Black"
BorderThickness="2" Padding="4" Background="LightGray">
<StackPal Orientation="Horizontal">
<TextBlock FontSize="20" FontWeight="Bold"
Text="{Binding GeneralForecast}" />
<TextBlock FontSize="16" Margin="10,0,0,0"
VerticalAlignment="Bottom"
Text="{Binding TemperatureLow,
StringFormat=Low: \{0:N2\}}" />
<TextBlock FontSize="16" Margin="10,0,0,0"
VerticalAlignment="Bottom"
Text="{Binding TemperatureHigh,
StringFormat='High: \{0:N2\}'}" />
<TextBlock FontSize="16" Margin="20,0,0,0"
VerticalAlignment="Bottom" Text="{Binding Percipitation,
StringFormat='Percip: \{0:N2\}'}" />
</StackPanel>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding GeneralForecast}"
Value="Sunny">
<Setter Property="Background" Value="Yellow"
TargetName="_border"/>
</DataTrigger>
<DataTrigger Binding="{Binding GeneralForecast}"
Value="Snowy">
<Setter Property="Background" Value="LightBlue"
TargetName="_border"/>
</DataTrigger>
<DataTrigger Binding="{Binding GeneralForecast}"
Value="Rainy">
<Setter Property="Background" Value="LightGreen"
TargetName="_border"/>
</DataTrigger>
<DataTrigger Binding="{Binding GeneralForecast}"
Value="Dry">
<Setter Property="Background" Value="LightYellow"
TargetName="_border"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Dependency Properties
DependencyProperties automatically enable a number of services that are not available to plain
properties. They are created very differently from plain properties and must be hosted inside a
DependencyObject (see Listing 2–1).

public class MyDependencyObject : DependencyObject


{
public static readonly DependencyProperty MyDependencyProperty;

public static MyDependencyObject()


{
MyDependencyProperty = DependencyProperty.Register("MyProperty", typeof(string),
public string MyProperty (*)
{
get { (string)GetValue(MyDependencyProperty); }
set { SetValue(MyDependencyProperty, value); }
}
}

(*) This is the property used in XAML


There are a number of notable differences here that set dependency properties apart from plain
properties.
• Dependency properties are declared public, static, and readonly.
• Dependency properties are registered via the static DependencyProperty.Register
method, inside the static constructor.
• The Register method requires the string name and type of an instance property
for the dependency property.
• The Register method requires the type of the host dependency object.
• There is an instance property that provides a façade for accessing the dependency
property as if it were a plain property.

XAML Integration

Listing 2–2. Setting a Property Value from within XAML Markup


<MyDependencyObject MyProperty="Test!" />

2.2 Databinding
Dependency properties can be set indirectly via databinding. This can use the binding object notation but, most
commonly, the binding expression extension is used, as shown in Listing 2–3.
Listing 2–3.

Binding a Button’s Content Property Using the Binding Expression Syntax

<Button Content="{Binding Source=myBindingSource, Path=myContent}" />

This syntax is a shorthand way of hooking up databinding to a dependency property

2.3 Property Value Inheritance


Because elements are organized in a tree structure, child elements can inherit properties from their
parents . The wrapped button will inherit MyProperty.

<MyDependencyObject MyProperty="Hello!">
<Button />
</MyDependencyObject>

public class MyDependencyObject : DependencyObject


{
public static MyDependencyObject()
{
MyDependencyProperty = DependencyProperty.RegisterAttached("MyProperty",
typeof(string), typeof(MyDependencyObject), new FrameworkPropertyMetadata
(string.Empty, FrameworkPropertyMetadataOptions.Inherits));
}

public static readonly DependencyProperty MyDependencyProperty;


public string MyProperty
{
get { (string)GetValue(MyDependencyProperty); }
set { SetValue(MyDependencyProperty, value); }
}
}

2.4 Styling
<Style x:Key="myButtonStyle">
<Setter Property="Control.Background" Value="Blue" />
</Style>
...
<Button Style="{StaticResource myButtonStyle}" />

2.5 Binding Sources


We’ve discussed the infrastructure required for the targets of databinding: they must be
DependencyProperties hosted by DependencyObjects. However, we haven’t looked at the other side of
the databinding coin: what types of objects can we bind from?

2.6 One-Way (Readonly) Binding


2.7 Two-Way (Read/Write) Binding

2.8 One-Way-To-Source Binding

2.9 One-Time Binding


2.10 The DataContext
All controls provided in the System.Windows.Controls namespace inherit from the FrameworkElement
class. This class has a property called DataContext, of type Object, which specifies the default binding
element for each control. Whenever controls are nested as children of other controls, they inherit the
DataContext value from their parent, as shown in Listing 2–11.

Listing 2–11. Inheriting DataContext Values from Parent Controls

<Window x:Class="MvvmWpfApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:MvvmWpfApp.ViewModel;assembly=MvvmWpfApp.ViewModel"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<viewModel:SampleViewModel x:Key="sampleViewModel1" />
<viewModel:SampleViewModel x:Key="sampleViewModel2" />
</Window.Resources>

<Grid DataContext="{StaticResource sampleViewModel1}">

<StackPanel Orientation="Vertical">

<StackPanel Orientation="Horizontal">
<Button Name="button1" />
<Button Name="button2" />
</StackPanel>

<StackPanel Orientation="Horizontal" DataContext="{StaticResource


sampleViewModel2}">
<Button Name="button3" />
<Button Name="button4" />
</StackPanel>

</StackPanel>
</Grid>
</Window>

In Listing 2–11, button1 and button2 will inherit their DataContext from their parent StackPanel. In
turn, that StackPanel inherits its DataContext from further up the logical tree, specifically from the Grid
control, whose DataContext has been explicitly set to sampleViewModel1 (via a StaticResource binding).
However, the DataContext of button3’s and button4’s parent has been overridden to reference
sampleViewModel2, so these two controls will also have a similar DataContext.
2.11 Advanced DataBinding

2.11.1 Binding Parameters

BindingGroupName
You can group bindings together and encapsulate the access of a number of different, but related,
bindings. Applications of this parameter are typically related to validation.
<TextBox Text="{Binding Path=myTextProperty, BindingGroupName=myBindingGroup}" />

BindsDirectlyToSource
When using a derivative of DataSourceProvider, such as ObjectDataProvider (which is covered later in
this chapter), you are binding to the underlying data via a provider. If you wish to bind to the provider
itself, you can set BindsDirectlyToSource to true, to override the default behavior.
<TextBox Text="{Binding Path=myDataSourceProvider, BindsDirectlyToSource=true}" />

Converter and ConverterParameter


The next section covers value converters in more detail. A common scenario for using a value converter is when binding a
Boolean source property to a UIElement’s Visibility target property: the former is a true/false value, while the latter is
an incompatible enumeration of the values Visible, Hidden and Collapsed.

<TextBox Text="{Binding myTextProperty}" Visibility="{Binding Path=isTextVisible, Converter={StaticResource


myBooleanToVisibilityConverter}}" />

ElementName
The source of bindings can be dependency properties, as we have seen. The corollary to this is that a
control may bind one of its properties to that of another control. In order to do this, the ElementName
parameter is specified to reference a specific control that is currently in scope.
<TextBox Text="Hello!" Name="textBox1" />
<TextBox Text="{Binding ElementName=textBox1, Path=Text}" />

FallbackValue
There are situations where a binding will succeed at compile time, but fail at runtime. Failure should
always be considered part of an application, and such circumstances need to be handled gracefully in
order to maintain a positive user experience. Users don’t expect software to be perfect, but they view
uncontained failure negatively and will treat your application very differently if messy failures are
endemic. Use the FallbackValue option to present your users with a friendly error message. If no
FallbackValue is specified, binding failure results in the default value for the type which, in the case of
string values, is the empty string.

<TextBox Text="{Binding Path=myTextProperty, FallbackValue='No value found'}" />

IsAsync _ VERY IMPORTANT!!


Setting IsAsync to true fetches the binding value asynchronously, allowing a long-running process to
proceed without blocking the rest of the view from binding. While the binding is retrieving the value, the FallbackValue is
displayed, so use this to present users with a suitable message asking for their patience.
<TextBox Text="{Binding Path=myTextProperty, IsAsync=true, FallbackValue='Please wait…'}" />

NotifyOnSourceUpdated and NotifyOnTargetUpdated


You may wish to be informed whenever the source or target values are updated by the databinding
mechanism. There are two steps to doing so: first, register an event handler for SourceUpdated,
TargetUpdated, or both; then, set the NotifyOnSourceUpdated or NotifyOnTargetUpdated (or both) bindin property to
true.
<TextBox Text="{Binding Path=myTextProperty, NotifyOnSourceUpdated=true}"
SourceUpdated="OnSourceUpdated" />

<TextBox Text="{Binding Path=myTextProperty, NotifyOnTargetUpdated=true}"


TargetUpdated="OnTargetUpdated" />

Your event handlers should reside in the code-behind file and look similar to this:
private void OnSourceUpdated(object sender, DataTransferEventArgs args)

NotifyOnValidationError
Validation is covered in Chapter 6, and the NotifyOnValidationError binding property is one method of handling validation
in WPF/Silverlight using the MVVM architecture.
<TextBox Text="{Binding Path=myTextProperty, NotifyOnValidationError=true}" Validation.Error="OnValidationError" />

private void OnValidationError(object sender, ValidationErrorEventArgs args)


{

}

Path
We have used the Path parameter extensively so far; its use is no secret. It is not strictly a required
parameter: with the DataContext set, either explicitly or by being passed down to the contained children, you can bind to
the DataContext by not specifying a path at all:

<StackPanel DataContext="{StaticResource myStringValue}">


<TextBox Text="{Binding}" />
</StackPanel>

Similarly, the Path parameter doesn’t need to be named if no other parameters are used in the
binding expression:

<TextBox Text="{Binding myTextProperty}" />

You can also use the dot notation (.) to drill down into subproperties on the bound object:

<TextBox Text="{Binding Path=myObject.MySubObject.MyBoundProperty}" />

If you have an indexed property, you can specify the index value as part of the Path:

<TextBox Text="{Binding Path=myIndexedProperty[2]}" />

Collection views, which expose the concept of a current item, can be bound using the slash notation
(/):
<TextBox Text="{Binding Path=myCollectionView/}" />

Source and RelativeSource


The DataContext supplies the bindings with the default Source, but it is common to bind to a separate object entirely. This
can be specified with the Source parameter:

<Window xmlns:viewModel="clr-namespace:BusinessModel;assembly=MyBusinessModel"
…>
<Window.Resources>
<viewModel:BusinessObject x:Key="myObject" />
</Window.Resources>
<TextBox Text="{Binding Path=MyTextProperty, Source={StaticResource myObject}}" />
</Window>
Source, however, references an object absolutely, whereas it can be useful to reference an object
relative to the binding target. The most common use is to bind to a property to another property on the same object:

<TextBox Text="{Binding Path=Foreground, RelativeSource={x:Static RelativeSource.Self}}" />

This example binds the Text property to the Foreground property of the TextBox (it binds to itself, so to speak). The
resulting text will be the name of the color of the text written in that same color.

StringFormat
Just like the String.Format method, StringFormat applies a string formatting expression to the binding
value before rendering the whole string to the view.
<TextBlock Text="{Binding Path=CurrentPrice, StringFormat='{0:c}'}" />
This example will output the CurrentPrice property (a decimal value) as the currently specified
culture’s currency value.
If a Converter is specified on the binding, in addition to the StringFormat, the Converter is applied first.

TargetNullValue
Whereas FallbackValue is used when the binding fails, TargetNullValue is used when the source of the
binding is null. It is useful for specifying default display values for null inputs.
<TextBox Text="{Binding Path=FirstName, TargetNullValue='Please enter your first name…'}" />

UpdateSourceExceptionFilter
As with NotifyOnValidationError, UpdateSourceExceptionFilter is used in data validation scenarios as
covered in Chapter 6.
<TextBox>
<TextBox.Text>
<Binding Path="FirstName" UpdateSourceExceptionFilter="ExceptionHandler">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>

private object ExceptionHandler(object bindingExpression, Exception exception)


{

}

UpdateSourceTrigger
There are three possible values—besides default—for the UpdateSourceTrigger enumeration.
PropertyChanged updates the binding source as soon as the target property’s value has changed.
LostFocus updates the binding source when the target control loses focus. Explicit doesn’t
automatically update the binding source; instead, it manually calls the UpdateSource method on the
BindingExpression. By default, the TextBox’s Text property has an UpdateSourceTrigger of LostFocus,

while most other controls default to PropertyChanged. Sometimes, you will want to override the TextBox’s default to
update the source as soon as the property is changed: that is, whenever the user types a new value into the textbox.
<TextBox Text="{Binding Path=FirstName, UpdateSourceTrigger=PropertyChanged}" />

XPath
If you are binding directly to XML data rather than object data, the Path property is replaced by the XPath property. XPath
is the XML Path language and is used to query XML data. You can construct XPath queries and set them to the XPath
parameter to bind to that data. XML databinding is outside of the scope of this book.
<TextBox Text="{Binding XPath=/Author[@FirstName='Gary' and @LastName='Hall']}" />

Data Conversion
IValueConverter Interface
The IValueConverter specifies two methods that must be implemented:

object Convert(object value, Type targetType, object parameter, CultureInfo culture);


object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);

<TextBlock Text="This is some sample text..."


Visibility="{Binding Source={StaticResource myDomainObject}, Path=ShowText,
FallbackValue={x:Static windows:Visibility.Visible},

Converter={StaticResource myBooleanToVisibilityConverter},
ConverterParameter={x:Static windows:Visibility.Collapsed}}" />

object value:
The value that the binding source or target produces. It is an object
because the IValueConverter interface does not know what type you will be using,
so it will have to be cast to the object that’s applicable.
True/false/ taken from ShowText

• Type targetType:
This is the type the binding target (or binding source in
ConvertBack) requires. It allows you to target a number of different binding targets
with a single IValueConverter implementation.
Boolean/Visibility/String/ etc

• object parameter:
ConverterParameter is a binding expression parameter. You
can specify this parameter on a per-binding basis to further customize the
outcome of your converter.
Taken from ConverterParameter: Collapsed;

• CultureInfo culture:
Many different types require culture-specific formatting.
Currencies are a prime example of this, and have myriad variations depending on
locale. The euro, for instance, is represented with at least three different notations.

Name Value Type


value true object {bool}
{Name = "Visibility" FullName =
▶ targetType System.Type {System.RuntimeType}
"System.Windows.Visibility"}
parameter Collapsed object {System.Windows.Visibility}
▶ culture {en-US} System.Globalization.CultureInfo
convertedValue null object
invisibleValue Visible System.Windows.Visibility

MultiValueConverter Interface
This coverter is the same as IValueConverter but instead it takes an array

object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);


object[] CovertBack(object value, Type[] targetTypes, object parameter, CultureInfo
culture);

Display Member Path


Being actually a shorthand for the more elaborate form :

<DataTemplate x:Key="itemTemplate">
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>

DisplayMemberPath binds to one property of the class that feeds the collection without the need to specify
the DataTemplate

public class GreekGod


{
private string name;

public string Name


{
get { return name; }
set { name = value; }
}

private string description;

public string Description


{
get { return description; }
set { description = value; }
}

private string romanName;

public string RomanName


{
get { return romanName; }
set { romanName = value; }
}

public GreekGod(string name, string description, string romanName)


{
this.name = name;
this.description = description;
this.romanName = romanName;
}
}

<Window.Resources>
<local:GreekGods x:Key="greekGods" />

<DataTemplate x:Key="itemTemplate">
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</Window.Resources>

<Border Margin="25"
Padding="5"
BorderBrush="RoyalBlue"
BorderThickness="2">
<StackPanel Orientation="Horizontal">
<ItemsControl Name="itemsControl1"
Width="150"
ItemTemplate="{StaticResource itemTemplate}"
ItemsSource="{StaticResource greekGods}" />
<ItemsControl Name="itemsControl2"
Width="150"
DisplayMemberPath="RomanName"
ItemsSource="{StaticResource greekGods}" />
</StackPanel>
</Border>
</Window>

You might also like