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:// ...
随机推荐
- Xtrabackup流备份与恢复
Xtrabackup是MySQL数据库的备份不可多得的工具之一.提供了全备,增备,数据库级别,表级别备份等等.最牛X的还有不落盘的备份,即流备份方式.对于服务器上空间不足,或是搭建主从,直接使用流式备 ...
- Linux/Unix shell 监控Oracle实例(monitor instance)
使用shell脚本实现对Oracle数据库的监控与管理将大大简化DBA的工作负担,如常见的对实例的监控,监听的监控,告警日志的监控,以及数据库的备份,AWR report的自动邮件等.本文给出Linu ...
- swfupload 参数说明
一.配置参数对象中的常用属性及说明 属性 类型 默认值 描述 upload_url String 处理上传文件的服务器端页面的url地址,可以是绝对地址,也可以是相对地址,当为相对地址时相对的是当 ...
- Redis 主从 Replication 的配置,主从复制原理
概述 Redis的replication机制允许slave从master那里通过网络传输拷贝到完整的数据备份.具有以下特点: 异步复制.从2.8版本开始,slave能不时地从master那里获取到数据 ...
- 因為 Hypervisor 未執行,所以無法啟動虛擬機器
bcdedit /set hypervisorlaunchtype auto https://technet.microsoft.com/zh-tw/magazine/2009.02.hyperv.a ...
- Java读取excel指定sheet中的各行数据,存入二维数组,包括首行,并打印
1. 读取 //读取excel指定sheet中的各行数据,存入二维数组,包括首行 public static String[][] getSheetData(XSSFSheet sheet) thro ...
- <面试经典题>输入框的功能测试点分析
(废话几句:这个是网上找来的一份模板,高亮部分为自己修改内容,且此面试题很像当年高考的“必考题”性质,触类旁通吧) 1. 输入框UI是否预计了输入内容长度(尽量完整的显示输入内容): 2. 输入框之前 ...
- Monitor traffic to localhost from IE or .NET
原文:http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/MonitorLocalTraffic Monitor traffic to lo ...
- 【C#】构造函数的特点
1.它的函数名与类名相同:2.它可以重载:3.不能指定返回类型,即使是void也不行:4.虽然在一般情况下,构造函数不被显式调用,而是在创建对象时自动被调用.但是并不是不能被显示调用.有些时候是一定要 ...
- C#学习7
一.变量交换 ; ; Console.WriteLine("开始a={0},b={1}",a,b); a = a + b; b = a - b; a = a - b; Consol ...