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:// ...
随机推荐
- (六)6.17 Neurons Networks convolutional neural network(cnn)
之前所讲的图像处理都是小 patchs ,比如28*28或者36*36之类,考虑如下情形,对于一副1000*1000的图像,即106,当隐层也有106节点时,那么W(1)的数量将达到1012级别,为了 ...
- HDU1010 Tempter of the Bone
解题思路:相当经典的一题,回溯,具体细节处理见代码. #include<cstdio> #include<cstring> #include<algorithm> ...
- 【解题报告】[动态规划] RQNOJ - PID38 / 串的记数
原题地址:http://www.rqnoj.cn/problem/38 解题思路: 状态表示:dp[i][j][k]表示i个A,j个B,k个C组成的满足条件的字符串的个数 初始状态:dp[0][0][ ...
- 警惕VPS服务商常用的超售手段
任何商业企业都希望将利益最大化,这是可以理解的.但如果做的过火最终损害的还是自己的利益.VPS服务提供商也一样,为了将利益最大化,他们往往会实用技术手段对所出售的VPS进行“超售”. 那么何谓“超售” ...
- $(function(){})和jQuery(function(){})
$(function(){})和jQuery(function(){})有没有区别,群里的屌丝争吵起来,各自讲着各种理论大道理.但还是有人给出了简而有力的证明: 区分大小写(jQuery) 但jQue ...
- Arduino 软重启 软件reset
将12脚连接一个1K电阻,然后用电阻另一端连接RESET脚.注意不是12脚直接连接RESET!! 代码如下(要注意RESET脚为LOW时自动重启) #define PIN 12 void setup( ...
- PHPMailer邮件类使用错误分析
PHPMailer配置清单如下: require_once ‘class.phpmailer.php‘; $receiver = ”; $mail = new PHPMailer ( ); $mai ...
- smarty缓存函数
原来在Smarty中在3.0以上版本中不在使用这个clear_all_cache(),而是以$smarty->clearAllCache(); 代替.其中$smarty->clear_ca ...
- 抛弃EF,20分构建一个属于自己的ORM框架
Poiuyt_cyc 博客园首页新随笔联系订阅管理随笔 - 11 文章 - 0 评论 - 111 抛弃EF,20分构建一个属于自己的ORM框架 相信EF大家都不陌生了,因为数据库表跟程序实体是一一 ...
- Drupal 7.23:函数drupal_alter()注释
/** * Passes alterable variables to specific hook_TYPE_alter() implementations. * * This dispatch fu ...