http://msdn.microsoft.com/en-us/magazine/cc163299.aspx#S1
Data Binding in WPF
John Papa
Code download available at:DataPoints2007_12.exe(161 KB)

Contents
By now, many of you know that Windows®
Presentation Foundation (WPF) makes it easy to design robust user
interfaces. But what you probably didn't know is that it also provides
powerful data-binding capabilities. With WPF, you can perform data
manipulation using Microsoft® .NET
Framework code, XAML, or a combination of both. You can bind to
controls, public properties, XML, or objects, making data binding quick,
flexible, and easier than ever. So let's take a look at how you can get
started binding your controls to the data sources of your choice.
Data Binding Specifics
To
use WPF data binding, you must always have a target and a source. The
target of the binding can be any accessible property or element that is
derived from DependencyProperty—an example is a TextBox control's Text
property. The source of the binding can be any public property,
including properties of other controls, common language runtime (CLR)
objects, XAML elements, ADO.NET DataSets, XML Fragments, and so forth.
To help you get the binding right, WPF includes two special
providers—the XmlDataProvider and the ObjectDataProvider.
Now let's take a look at how the WPF data-binding techniques work and I'll present practical examples that illustrate their use.
Creating a Simple Binding
Let's
start with a simple example that illustrates how to bind a TextBlock's
Text property to a ListBox's selected item. The code displayed in Figure 1
shows a ListBox that has six ListBoxItems declared. The second
TextBlock in the code example has a property called Text (specified in
XAML property-element syntax with the XML child element
<TextBlock.Text>), which will contain the text for the TextBlock.
The Text property declares a binding to the ListBox's selected item with
the <Binding> tag. The ElementName attribute of the Binding tag
indicates the name of the control that the TextBlock's Text property is
bound to. The Path attribute indicates the property of the element (in
this case the ListBox) that we will be binding to. The result of this
code is that when a color is selected from the ListBox, the name of that
color is shown in the TextBlock.

Figure 1 Basic but Verbose Binding to a Control
<StackPanel> <TextBlock Width="248" Height="24" Text="Colors:" TextWrapping="Wrap"/> <ListBox x:Name="lbColor" Width="248" Height="56"> <ListBoxItem Content="Blue"/> <ListBoxItem Content="Green"/> <ListBoxItem Content="Yellow"/> <ListBoxItem Content="Red"/> <ListBoxItem Content="Purple"/> <ListBoxItem Content="Orange"/> </ListBox> <TextBlock Width="248" Height="24" Text="You selected color:" /> <TextBlock Width="248" Height="24"> <TextBlock.Text> <Binding ElementName="lbColor" Path="SelectedItem.Content"/> </TextBlock.Text> </TextBlock> </StackPanel>
The code listed in Figure 1 can be modified slightly to use a shorthand syntax for data binding. For example, let's replace the TextBlock's <Binding> tag with the following code snippet:
<TextBlock Width="248" Height="24" Text="{Binding ElementName=lbColor, Path=SelectedItem.Content}" />
This syntax, called the attribute syntax, condenses the data binding code inside of the Text attribute of the TextBlock. Basically, the Binding tag gets pulled inside of the curly braces along with its attributes.
Binding Modes
I can take the previous example further, binding the background color of the TextBlock to the color that is selected in the ListBox. The following code adds a Background property to the TextBlock and uses the attribute binding syntax to bind to the value of the selected item in the ListBox:
<TextBlock Width="248" Height="24" Text="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=OneWay}" x:Name="tbSelectedColor" Background="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=OneWay}"/>
When the user selects a color in the ListBox, the name of that color will appear in the TextBlock and the background color of the TextBlock will change to the selected color (see Figure 2).

Figure 2 Binding a Source to Two Targets
Notice the statement in the previous example that sets the Mode attribute to OneWay. The Mode attribute defines the binding mode that will determine how data flows between the source and the target. In addition to OneWay, there are three other binding modes available: OneTime, OneWayToSource, and TwoWay,
When using OneWay binding, as shown in the preceding code snippet, the data flows from the source to the target each time a change is made on the source. And while I explicitly specified this binding mode in my example, OneWay binding is the default binding mode for the TextBlock's Text property and does not need to be specified. Like OneWay binding, OneTime binding sends data from the source to the target; however, it does this only when the application is started or when the DataContext changes and, as a result, does not listen for change notifications in the source. Unlike OneWay and OneTime binding, OneWayToSource binding sends data from the target to the source. Finally, TwoWay binding sends the source data to the target, and if there are changes in the target property's value, those will be sent back to the source.
In the previous example, I used OneWay binding because I wanted the source (the selected ListBoxItem) to be sent to the TextBlock whenever a change is made in the ListBox selection. I do not want changes from the TextBlock to go back to the ListBox. Of course, there is no way for a user to edit a TextBlock. If I want to explore TwoWay binding, I can add a TextBox to this code, bind its text and background color to the ListBox, and set the Mode to TwoWay. When a user selects a color in the ListBox, the color is shown in the TextBox and its background color changes. When that user types in a color (such as Cyan) in the TextBox, the name of the color is updated in the ListBox (target to source) and in turn, since the ListBox was updated, the new value is sent to all elements that are bound to the ListBox's SelectedItem property. This means that the TextBlock will also have its color updated and its text value set to the new color (see Figure 3).

Figure 3 TwoWay Binding in Action
Here's the code I used to bind the TextBlock (OneWay) and the TextBox (TwoWay) to the ListBox:
<TextBlock Width="248" Height="24" Text="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=OneWay}" x:Name="tbSelectedColor" Background="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=OneWay}"/> <TextBox Width="248" Height="24" Text="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=TwoWay}" x:Name="txtSelectedColor" Background="{Binding ElementName=lbColor, Path=SelectedItem.Content, Mode=OneWay}"/>
If I change the TwoWay mode back to OneWay, the user will be able to edit the color in the TextBox without causing the changed value to be sent back to the ListBox.
Selecting the appropriate binding mode is important. I often employ OneWay when I want to display read-only data to a user. I use TwoWay binding when I want the user to be able to change the data in the control and have that change reflected in the data source (a DataSet, object, XML, or another bound control). I find OneWayToSource to be a good choice when I want to allow a user to change the data source without having the data source bind its data back to the target. I have used OneTime binding when I was tasked with showing, in a read-only control, the state of the data as it was when the screen loaded. Using OneTime binding, a series of read-only controls was bound to the data and, as the user interacted with the form and the data source's values were changed, the bound controls remained unchanged. This provided a way for the users to compare the changes that were made. Additionally, OneTime binding is a good choice when your source doesn't implement INotifyPropertyChanged.
A Time to Bind
In the previous example, the TextBox allows TwoWay binding to the selected ListBoxItem in the ListBox. This flow of data from the TextBox back to the ListBox happens when the TextBox loses focus. To change the event that causes the data to be sent back to the source, you can specify a value for UpdateSourceTrigger, which is the binding property that defines when the source should be updated. There are three values that can be set for the UpdateSourceTrigger: Explicit, LostFocus, and PropertyChanged.
When you set the UpdateSourceTrigger to Explicit, the source will not be updated unless the BindingExpression.UpdateSource method is called from code. The LostFocus setting (the default value for the TextBox control) indicates that the source will be updated when the target control loses focus. The PropertyChanged value indicates that the target will update the source every time the target control's bound property changes. This setting is useful when you want to dictate when the binding will occur.
Binding to XML
Binding to data sources such as XML and objects is also handy. Figure 4 shows a sample of an XmlDataProvider that contains an embedded list of colors that will be used as a data source. The XmlDataProvider can be used to bind to an XML document or fragment that is either embedded in the XmlDataProvider tag or is in a file referred to in an external location.

Figure 4 XmlDataProvider
<StackPanel> <StackPanel.Resources> <XmlDataProvider x:Key="MoreColors" XPath="/colors"> <x:XData> <colors > <color name="pink"/> <color name="white"/> <color name="black"/> <color name="cyan"/> <color name="gray"/> <color name="magenta"/> </colors> </x:XData> </XmlDataProvider>
Embedded XML content must be placed within a <x:XData> tag inside of an XmlDataProvider, as shown in Figure 4. The XmlDataProvider must be given an x:Key value so that it can be referred to by data-binding targets. Notice that the XPath attribute is set to "/colors". This attribute defines the level of the XML content that will be used as the data source. This becomes very useful when binding to a large XML structure that may be contained in a file or database and the data you want to bind to is not the root element.
An XmlDataProvider is a resource that can be placed inside of a context-specific resource. As Figure 4 shows, the XmlDataProvider is defined as a resource within the context of the StackPanel. This means that the XmlDataProvider will be available to all content inside of that StackPanel. Setting the context of a resource helps limit the exposure of a data source to the appropriate areas. This enables you to create well-defined, self-contained regions of both controls and supporting resources within your page, thus improving readability.
The syntax for binding to a resource is slightly different than it is for binding to an element. When binding to a control, you set the ElementName and the Path properties of the Binding. However, when you bind to a resource you set the Source and, since we are binding to an XmlDataProvider, you set the XPath property of the Binding as well. For example, the following code will bind the ListBox's items to the MoreColors resource. The Source property is set to a resource and it is specified as a StaticResource named MoreColors. The XPath property indicates that the items will be bound to the <color> element's name attribute within the XML data source:
<ListBox x:Name="lbColor" Width="248" Height="56" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource MoreColors}, XPath=color/@name}"> </ListBox>
I specified StaticResource in this case because the XML will not change. If changes occur in the data source, they will not be sent to the target. The DynamicResource setting indicates the opposite—changes will be sent. This is useful when referencing system themes, languages in globalization, or fonts. A DynamicResource will allow these types of settings to be propagated throughout the UI elements that are bound to them dynamically.
The XmlDataProvider can also point to an external source for the XML content. For my example, I have a file named colors.xml that contains the list of colors I want my ListBox to be bound to. I can simply add a second XmlDataProvider resource to the StackPanel and direct it to the XML file. Notice I set the Source attribute to the name of the XML file and the x:Key to Colors:
<XmlDataProvider x:Key="Colors" Source="Colors.xml" XPath="/colors"/>
Both XmlDataProviders exist as resources within the same StackPanel. I can tell the ListBox to bind itself to this new resource by changing the name that the StaticResource is set to:
<ListBox x:Name="lbColor" Width="248" Height="56" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource Colors}, XPath=color/@name}"> </ListBox>
Object Binding and DataTemplates
While the XmlDataProvider works great for XML, when you want to bind to an object or a list of objects, you can create an ObjectDataProvider as a resource. The ObjectDataProvider's ObjectType designates the object that will provide the data‑binding source while the MethodName indicates the method that will be invoked to get the data. For example, assuming I have a class called PersonService that has a method called GetPersonList that returns a List<Person>, the ObjectDataProvider would look like this:
<StackPanel.Resources> <ObjectDataProvider x:Key="persons" ObjectType="{x:Type svc:PersonService}" MethodName="GetPersonList"></ObjectDataProvider> </StackPanel.Resources>
If you want a more complete look, the PersonService and Person classes, as well as all other sample code, are contained in the code that accompanies this column.
There are a handful of other properties that are available on the ObjectDataProvider. The ConstructionParameters property allows you to pass parameters to the constructor of the class being invoked. You can also specify parameters using the MethodParameters property, and you can use the ObjectInstance property to specify an existing instance of an object as the source.
If you want the data to be retrieved asynchronously, you can set the IsAsynchronous property of the ObjectDataProvider to true. Then the user will be able to interact with the screen while waiting for the data to populate in the target control that is bound to the ObjectDataProvider's source.
When adding an ObjectDataProvider, you have to qualify the namespace of the data-source class. In this case, I have to add an xmlns attribute to the <Window> tag so that the svc shortcut is qualified and indicates the proper namespace:
xmlns:svc="clr-namespace:DataBindingWPF"
Now that the data source is defined via the ObjectDataProvider, I want to bind items in a ListBox control to this data. I want to display two lines of text in each ListBoxItem. The first line will display the FullName property of the Person instance in bold and the second line will show the Title and City of the instance. In XAML, this is quite simple using DataTemplates, which allow you to define a data visualization strategy that can be reused.
Figure 5 shows the completed XAML, which has a DataTemplate defined to display the Person information in the layout I designated. I set the DataType property of the DataTemplate to indicate that the DataTemplate will be referring to the Person class type. I do not specify the actual binding in the DataTemplate, as I will do this in the ListBox control. By omitting the Binding Source, the binding will be made to the current DataContext in scope.
In Figure 5, I set the ListBox's ItemsSource property to bind to the persons resource so that I could bind the data to the ListBox but not format it. The data is correctly displayed by setting the ItemTemplate property to the personLayout resource, which is the DataTemplate's key name. The ultimate result is a screen that looks like Figure 6.

Figure 5 Object Binding
<Window x:Class="DataBindingWPF.ObjectBinding" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:svc="clr-namespace:DataBindingWPF" Title="DataBindingWPF" Height="300" Width="300"> <StackPanel> <StackPanel.Resources> <ObjectDataProvider x:Key="persons" ObjectType="{x:Type svc:PersonService}" MethodName="GetPersonList" ></ObjectDataProvider> <DataTemplate x:Key="personLayout" DataType="Person"> <StackPanel Orientation="Vertical"> <TextBlock Text="{Binding Path=FullName}" FontWeight="Bold" Foreground="Blue"> </TextBlock> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Title}"></TextBlock> <TextBlock Text=", "></TextBlock> <TextBlock Text="{Binding Path=City}"></TextBlock> </StackPanel> </StackPanel> </DataTemplate> </StackPanel.Resources> <TextBlock></TextBlock> <ListBox x:Name="lbPersons" ItemsSource="{Binding Source={StaticResource persons}}" ItemTemplate="{DynamicResource personLayout}" IsSynchronizedWithCurrentItem="True"/> </StackPanel> </Window>

Figure 6 Using a DataTemplate
Sorting the Data
If you want to sort your data in a specific way, you can bind to a CollectionViewSource instead of directly to the ObjectDataProvider. The CollectionViewSource then becomes the data source and serves as an intermediary that intercepts the data from the ObjectDataProvider; provides sorting, grouping, and filtering functionality; and then propagates it to the target.
The CollectionViewSource shown next has its Source attribute set to the resource name of the ObjectDataProvider (persons). I then defined a sort order for the data by indicating the properties to sort by and their direction:
<CollectionViewSource x:Key="personView" Source="{Binding Source={StaticResource persons}}"> <CollectionViewSource.SortDescriptions> <ComponentModel:SortDescription PropertyName="City" Direction="Ascending" /> <ComponentModel:SortDescription PropertyName="FullName" Direction="Descending" /> </CollectionViewSource.SortDescriptions> </CollectionViewSource>
The DataContext is used to bind all controls within a container control to a data source. This is very useful when you have several controls that all use the same binding source. The code could get repetitive if you indicated the binding source for every control. Instead, you can set the DataContext for the container of the controls to the binding source and simply omit the Source attribute from the contained controls. For example, here is a series of TextBlocks bound explicitly to the same binding source:
<StackPanel> <TextBlock Text="{Binding Source={StaticResource personView}, Path=FullName}"></TextBlock> <TextBlock Text="{Binding Source={StaticResource personView}, Path=Title}"></TextBlock> <TextBlock Text="{Binding Source={StaticResource personView}, Path=City}"></TextBlock> </StackPanel>
Here are the same three TextBoxes bound to the DataContext, which refers back to the controls' StackPanel container:
<StackPanel DataContext="{Binding Source={StaticResource personView}}" > <TextBlock Text="{Binding Path=FullName}"></TextBlock> <TextBlock Text="{Binding Path=Title}"></TextBlock> <TextBlock Text="{Binding Path=City}"></TextBlock> </StackPanel>
If the container does not define a DataContext, then it will continue to look at the next outer nested container until it finds the current DataContext.
Forging Ahead
WPF data binding offers a great deal of flexibility and control over the type of data that can be bound to, and how it can be controlled and displayed. With so much power and so many choices, I'm sure you'll want to get your hands dirty right away.
Send your questions and comments for John to mmdata@microsoft.com.
- WPF binding<一> Data Binding在WPF中的地位
在代码中看到 <Image Source="{Binding ElementName=LBoxImages, Path=SelectedItem.Source}" /> ...
- csharp: Data binding in WPF DataGrid control
<Window x:Class="WpfProjectDemo.MainWindow" xmlns="http://schemas.microsoft.com/wi ...
- WPF QuickStart系列之数据绑定(Data Binding)
这篇博客将展示WPF DataBinding的内容. 首先看一下WPF Data Binding的概览, Binding Source可以是任意的CLR对象,或者XML文件等,Binding Targ ...
- .NET: WPF Data Binding
WPF是分离UI和Logic的最佳工具,不同于Window Form的事件驱动原理,WPF采用的是数据驱动,让UI成为了Logic的附属,达到分离的效果. 本篇主要讲讲wpf的精华:data bind ...
- [WPF]如何调试Data Binding
前言 在WPF开发中,将ViewModel中对象绑定到UI上时,会出现明明已经将数据对象Binding到UI,但是UI上就是不显示等等的问题.这篇博客将介绍WPF Data Binding相关的内容, ...
- WPF之数据绑定Data Binding
一般情况下,应用程序会有三层结构:数据存储层,数据处理层(业务逻辑层),数据展示层(UI界面). WPF是“数据驱动UI”. Binding实现(通过纯C#代码) Binding分为source和ta ...
- WPF中的Data Binding调试指南
大家平时做WPF开发,相信用Visual studio的小伙伴比较多.XAML里面曾经在某些特殊版本的Visual Studio中是可以加断点进行调试的,不过目前多数版本都不支持在XAML加断点来调试 ...
- WPF教程三:学习Data Binding把思想由事件驱动转变为数据驱动
之前大家写代码都喜欢用事件驱动,比如说鼠标输入的click事件.初始化的内容全部放在窗体加载完毕的load事件,等等,里面包含了大量的由事件触发后的业务处理代码.导致了UI和业务逻辑高度耦合在一个地方 ...
- WPF中的数据绑定Data Binding使用小结
完整的数据绑定的语法说明可以在这里查看: http://www.nbdtech.com/Free/WpfBinding.pdf MSDN资料: Data Binding: Part 1 http:// ...
随机推荐
- 《C和指针》读书笔记 第2章-基本概念
原创文章,转载请注明出处:http://www.cnblogs.com/DayByDay/p/3936485.html
- 数据结构——Java实现单向链表
结点类: /** * @author zhengbinMac * 一个OnelinkNode类的对象只表示链表中的一个结点,通过成员变量next的自引用方式实现线性表中各数据元素的逻辑关系. */ p ...
- 【UVa-514】铁轨——栈的学习
UVa514 Rails(铁轨) 题目:铁轨 题目链接: UVa514链接 题目描述: 某城市有一个火车站,有n节车厢从A方向驶入车站,按进站的顺序编号为1-n.你的任务是判断是否能让它们按照某种特定 ...
- bjfu1253 最大上升子序列和
n^2的算法就行,很简单的动态规划.直接上代码 /* * Author : ben */ #include <cstdio> #include <cstdlib> #inclu ...
- ASP.NET Cookie对象到底是毛啊?(简单小例子)
记得刚接触asp.net的时候,就被几个概念搞的头痛不已,比如Request,Response,Session和Cookie.然后还各种在搜索引擎搜,各种问同事的,但是结果就是自己还是很懵的节奏. 那 ...
- margin四个元素的顺序
如果margin给的是四个值比如:margin:0px 0px 0px 0px;代表:margin: top right bottom left代表从上右下左,顺时针方向.如果margin给的是三个值 ...
- VC++2010配置使用MySQL5.6
0.前提 安装后的文件概览 编译器: VC++2010 MySQL版本:MySQL5.6.19 for win64 Connector版本:connector c++ 1.1.3 在VS2010 ...
- MySQL_PHP学习笔记_2015_0614_PHP传参总结_URL传参_表单传参
1. PHP 传参总结 1.1 url 传参 解析方法(下面两种解读方式均可以): $firstName1 = $_GET['firstName']; $firstName2 = $_RE ...
- 【Unity入门】碰撞检测与触发检测
版权声明:本文为博主原创文章,转载请注明出处. 在Unity里面,游戏物体的碰撞我们可以通过刚体组件(Rigidbody)和碰撞器组件(Collider)来进行检测.首先在场景里面添加一个Plane面 ...
- fopen警告处理方式
warning C4996: “fopen”被声明为否决的 问题:vs2005中编程时,遇到如下: warning C4996: “fopen”被声明为否决的. 解释:微软的警告,主要是那些都是C库的 ...