您的位置:首页 > 其它

Windows Presentation Foundation 数据绑定:第一部分

2007-05-19 08:24 633 查看


本页内容


简介


简化的 XAML 绑定


我们所处的位置


参考资料

简介

Windows Presentation Foundation(以前称作 Avalon)为胖客户端开发用户界面引入了一个意义深远的新方法。WPF 第一次将用户界面设计与代码设计相分离。这种分离意味着,通常标记在一个文件中而代码则在另一个文件中,这与 ASP.NET 很类似。然而,这种分离仅在编译时存在。标记文件用于生成形成代码文件的代码,进而生成应用程序。

为了便于设计,Microsoft 开发了一种丰富的标记语言,称作 XAML。XAML 是一种基于 XML 的标记语言,它支持一个用于开发特定应用程序的新模型,这些应用程序具有对许多不同的用户界面概念的本机支持,如 2D 和 3D 绘图、动画、控件包容、控件和文档流,以及一个丰富的数据绑定模型。本文将概述 WPF 数据绑定,并假定您对 WPF 有一定的了解。如果您还不了解 WPF,请参阅 Tim Sneath 的 Architectural Overview of the Windows Presentation Foundation Beta 1 Release 一文进行概览。

为什么使用数据绑定?

如果您要开始使用 WPF,可能想知道:不用学习数据绑定,只编写代码来执行项目中的大部分数据操作是否更容易。虽然这可能是一个有效的方法,但我猜想您将逐渐使用基于 XAML 的数据绑定,甚至可能会爱上它。下面我们来看一个小示例。

图 1 显示一个简单 WPF 项目的用户界面。它是 RSS 提要的编辑器,允许用户查看和编辑提要。



图 1. 我们的 RSS 编辑器

该编辑器的布局相当简单,如以下 XAML 代码所示。

<Window x:Class="ExampleCS.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ExampleCS"
Loaded="Window1_Loaded" >
<StackPanel>
<TextBlock HorizontalAlignment="Center" FontWeight="Bold">
BlogEditor
</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<ListBox Name="entryListBox"
Height="300"
SelectionChanged="entryListBox_Changed"/>
<Grid Width="500" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="*" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0">Title:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Name="titleText" />
<TextBlock Grid.Row="1" Grid.Column="0">Url:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" Name="urlText" />
<TextBlock Grid.Row="2" Grid.Column="0">Date:</TextBlock>
<TextBox Grid.Row="2" Grid.Column="1" Name="dateText" />
<TextBlock Grid.Row="3" Grid.Column="0">Body:</TextBlock>
<TextBox Grid.Row="3" Grid.Column="1"
Name="bodyText"
TextWrapping="Wrap" />
<Button Grid.Row="4"
Grid.ColumnSpan="2"
Grid.Column="1"
Click="updateButton_Click">
Update
</Button>
</Grid>
</StackPanel>
</StackPanel>
</Window>

请注意加粗显示的事件处理程序。那里是大部分代码将发生的地方,加载 RSS 提要并填充 WPF 控件。

C#:

XMLDocument blog = new XMLDocument();
const string BLOGURL = @"z:/adoguy.RSS";

public Window1()
{
InitializeComponent();
blog.Load(BLOGURL);
}

void Window1_Loaded(object sender, RoutedEventArgs e)
{
FillListBox();
}

void FillListBox()
{
entryListBox.Items.Clear();

XMLNodeList nodes = blog.SelectNodes("//item");
foreach (XMLNode node in nodes)
{
ListBoxItem item = new ListBoxItem();
item.Tag = node;
item.Content = node["title"].InnerText;
entryListBox.Items.Add(item);
}
}

Visual Basic .NET:

Dim blog As New XMLDocument
Const BLOGURL As String = "z:/adoguy.RSS"

Public Sub New()
InitializeComponent()
blog.Load(BLOGURL)
End Sub

Sub Window1_Loaded(ByVal sender As Object, _
ByVal e As RoutedEventArgs)
FillListBox()

End Sub

Sub FillListBox()

entryListBox.Items.Clear()

Dim nodes As XMLNodeList = blog.SelectNodes("//item")

For Each node As XMLNode In nodes

Dim item As New ListBoxItem
item.Tag = node
item.Content = node("title").InnerText
entryListBox.Items.Add(item)

Next

End Sub

在这段代码中,您可以看到:我们用 RSS 提要加载一个 XML 文档,用所有项的标题填充 ListBox

接下来,我们需要处理在 ListBox 中进行选择时将发生的事情。

C#:

void entryListBox_Changed(object sender, RoutedEventArgs e)
{
if (entryListBox.SelectedIndex != -1)
{
XMLNode node = ((ListBoxItem)entryListBox.SelectedItem).Tag as XMLNode;
if (node != null)
{
titleText.Text = node["title"].InnerText;
URLText.Text = node["guid"].InnerText;
dateText.Text = node["pubDate"].InnerText;
bodyText.Text = node["description"].InnerText;
}
}
}

Visual Basic .NET:

Sub entryListBox_Changed(ByVal sender As Object, _
ByVal e As SelectionChangedEventArgs)

If entryListBox.SelectedIndex <> -1 Then

Dim node As XMLNode = CType(entryListBox.SelectedItem, ListBoxItem).Tag
If Not node Is Nothing Then

titleText.Text = node("title").InnerText
URLText.Text = node("guid").InnerText
dateText.Text = node("pubDate").InnerText
bodyText.Text = node("description").InnerText

End If

End If

End Sub

ListBox 更改时,我们用所选的 RSS 提要项填充 TextBoxes。可以通过获取提要项的内部文本来执行该操作。请注意,我们还需要用 ListBoxItem, 保留节点的一份副本,进行一些转换以到达每个事件处理程序。

最后,我们需要处理单击 Update 按钮时发生的事情。

C#:

void updateButton_Click(object sender, RoutedEventArgs e)
{
if (entryListBox.SelectedIndex != -1)
{
XMLNode node = ((ListBoxItem)entryListBox.SelectedItem).Tag as XMLNode;
if (node != null)
{
node["title"].InnerText = titleText.Text;
node["guid"].InnerText = URLText.Text;
node["pubDate"].InnerText = dateText.Text;
node["description"].InnerText = bodyText.Text;

blog.Save(BLOGURL);

FillListBox();
}
}
}

Visual Basic .NET:

Sub updateButton_Click(ByVal sender As Object, _
ByVal e As RoutedEventArgs)

If entryListBox.SelectedIndex <> -1 Then

Dim node As XMLNode = CType(entryListBox.SelectedItem, ListBoxItem).Tag

If Not node Is Nothing Then

node("title").InnerText = titleText.Text
node("guid").InnerText = URLText.Text
node("pubDate").InnerText = dateText.Text
node("description").InnerText = bodyText.Text

blog.Save(BLOGURL)

FillListBox()

End If

End If

End Sub

在此处,假如更改了标题,我们用新信息更新节点,保存 XML 文档,并导致重新填充 ListBox。尽管这只是一个简单的小应用程序,但需要的代码还是有点儿多。使用 XAML 数据绑定执行该操作是否会简单些?是的,会更简单。以下是同一个项目的 XAML,使用 XAML 数据绑定。

<StackPanel.Resources>
<b><XMLDataProvider x:Key="RSSFeed" Source="z:/adoguy.RSS" /></b>
</StackPanel.Resources>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
Blog Editor
</TextBlock>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<ListBox Name="entryListBox"
Height="300"
<b>ItemsSource="{Binding Source={StaticResource RSSFeed}, XPath=//item}"</b>
>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock <b>Text="{Binding XPath=title}"</b> />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid Width="500"
Margin="5"
<b>DataContext="{Binding ElementName=entryListBox, Path=SelectedItem}"</b> >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="25" />
<RowDefinition Height="*" />
<RowDefinition Height="25" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0">Title:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1"
Name="titleText"
<b>Text="{Binding XPath=title}"</b> />
<TextBlock Grid.Row="1" Grid.Column="0">URL:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1"
Name="URLText"
<b>          Text="{Binding XPath=guid}"</b> />
<TextBlock Grid.Row="2" Grid.Column="0">Date:</TextBlock>
<TextBox Grid.Row="2" Grid.Column="1"
Name="dateText"
<b>Text="{Binding XPath=pubDate}"</b> />
<TextBlock Grid.Row="3" Grid.Column="0">Body:</TextBlock>
<TextBox Grid.Row="3" Grid.Column="1"
Name="bodyText"
TextWrapping="Wrap"
<b>Text="{Binding XPath=description}"</b> />
<Button Grid.Row="4" Grid.ColumnSpan="2" Grid.Column="1" >
Update
</Button>
</Grid>
</StackPanel>
</StackPanel>

这段 XAML 代码运行时没有任何隐藏的代码。图 2 显示只使用 XAML 的应用程序(使用 XAMLPad)。



图 2. XAMLPad 中的 RSS 编辑器

您可能想知道"它是如何运行的"?它之所以运行,是因为我们使用 XAML 绑定来为我们做大量的工作。虽然以后会详细介绍 XAML 中涉及的每项技术,但我们还是先浏览一下数据绑定的各部分内容,从而解释它在实际工作中的情况。

首先,创建一个 XMLDataProvider 对象来加载和管理编辑器的 XML 文档。

<XmlDataProvider x:Key="RssFeed" Source="z:/adoguy.RSS" />

它告诉 XAML 从 Z: 驱动器加载一个 XML 文档,以填充窗体。

接下来,绑定 ListBox

<ListBox Name="entryListBox" Height="300" ItemsSource="{Binding Source={StaticResource RssFeed}, XPath=//item}" >

这段代码告诉列表框查找名为 RSSFeed 的 XAML 中的资源,然后将其用作数据源。此外,它还告诉列表框从 XPath 表达式获得要绑定到的项的列表(在本例中是文档中的所有项元素)。

接下来,通过指定数据模板来指定要在列表框的各项中显示的内容。

<DataTemplate> <TextBlock Text="{Binding XPath=title}" /> </DataTemplate>

这段代码告诉 ListBox 为每项创建一个 TextBlock 对象,并使用 XPath 确定要在 TextBlock 中显示的内容。

接下来,绑定包含所有详细信息的网格。

<Grid Width="500" Margin="5" DataContext="{Binding ElementName=entryListBox, Path=SelectedItem}" >

在此处,我们告诉 XAML 将容器(在本例中是 Grid)绑定到 ListBox 的选定项。我们使用 ElementName 而不是 Source,因为我们希望绑定到 XAML 文档中的某个控件,而不是一些外部数据。通过设置 DataContext,允许将 Grid 中的所有控件设置为同一个对象(在本例中是 SelectedItem)。

接下来,我们将每个 TextBox 绑定到所需的 XML 文档部分。

<TextBlock Grid.Row="0" Grid.Column="0">Title:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Name="titleText" Text="{Binding XPath=title}" />
<TextBlock Grid.Row="1" Grid.Column="0">Url:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" Name="urlText" Text="{Binding XPath=guid}" />
<TextBlock Grid.Row="2" Grid.Column="0">Date:</TextBlock>
<TextBox Grid.Row="2" Grid.Column="1" Name="dateText" Text="{Binding XPath=pubDate}" />
<TextBlock Grid.Row="3" Grid.Column="0">Body:</TextBlock>
<TextBox Grid.Row="3" Grid.Column="1" Name="bodyText" TextWrapping="Wrap" Text="{Binding XPath=description}" />

由于我们设置了 DataContext,因此可以仅指定 XPath 表达式,以获得我们需要的 RSS 提要的部分。

一下尝试接受这些内容太多了。停下来喘口气。我并不指望你们一下子都能接受。在下面部分中,我将前面示例的许多观点分成各个更易于管理的部分。



返回页首

简化的 XAML 绑定

要从一个有关 Binding 对象如何工作的简单示例开始,我们先从下面这个非常简单的 XAML 文档入手。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<Canvas>
<TextBox Text="This is a TextBox" />
<TextBlock Canvas.Top="25" >Test</TextBlock>
</Canvas>
</Window>

这段代码创建了一个简单的画布,包含两个控件,如图 3 所示。



图 3. 简单的 XAML 画布

我们可能希望绑定 TextBlock,以便按照键入的方式显示 TextBox 的文本。为此,我们需要一个 Binding 对象将两个对象绑定在一起。首先要向 TextBox 添加一个名称,这样我们才能通过元素名引用元素。

<TextBox Name="theTextBox" />

接下来,我们需要向 TextBlockText 元素添加一个 Binding

<TextBlock Canvas.Top="25"> <TextBlock.Text> <Binding ElementName="theTextBox" Path="Text" /> </TextBlock.Text> </TextBlock>

这段代码告诉 TextBlockText 要设置为 TextBox 控件中的用户类型。

将以上这几段代码组合在一起即可产生以下代码。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<Canvas>
<TextBox Name="theTextBox" Text="Hello" />
<TextBlock Canvas.Top="25">
<TextBlock.Text>
<Binding ElementName="theTextBox" Path="Text" />
</TextBlock.Text>
</TextBlock>
</Canvas>
</Window>

这段 XAML 代码创建了一个窗体,该窗体按照在 TextBox 中键入的内容更改 TextBlock,如图 4 所示。



图 4. 绑定控件

祝贺您!您已经拥有了自己的第一个绑定!但是这个 XML 语法有点冗长。应该有更好的编写方法。

使用绑定简化版本

在上一示例中我们了解到,如何将 Binding 元素添加到属性来创建数据绑定。在这个简单的示例中,以这种方式进行数据绑定似乎不太麻烦;然而,随着 XAML 文档的增大,这个冗长的语法可能会变得比较麻烦。为了缓解这个问题,XAML 支持绑定语法的一个简化版本。

例如,使用简化版本,上一示例如下所示。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<Canvas>
<TextBox Name="theTextBox" Text="Hello" />
<TextBlock Canvas.Top="25"
Text="{Binding ElementName=theTextBox, Path=Text}" />
</Canvas>
</Window>

简化语法包含在大括号 ({}) 中,以单词 Binding 开始,包含绑定属性的名称/值对。简化语法的目的是使数据绑定需要更少的击键,并且更易于阅读。本文的剩余部分,我将使用简化语法。

绑定源

目前为止,我们已经将另一个控件用作所有绑定示例的源。然而,在大多数基于 XAML 的项目中,您将绑定到除其他控件外的源。大多数数据绑定的关键是 Source 属性。在前面的示例中,我们使用的是 ElementName 属性(它用于绑定到一个控件),而不是使用 Source 属性。对于大多数应用程序,您希望绑定到更重要的源,如 XML 或 .NET 对象。XAML 用其 provider 对象支持该操作。XAML 中内置有两种类型的数据提供程序:ObjectDataProviderXMLDataProviderObjectDataProvider 用于绑定到 .NET 对象以及从 .NET 对象绑定,并不奇怪的是,XMLDataProvider 用于绑定到 XML 片段和文档以及从 XML 片段和文档进行绑定。您可以在任何 XAML 容器的资源部分中指定一个数据提供程序。

使用 XMLDataProvider

例如:

<StackPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel.Resources>
<XmlDataProvider x:Key="FavoriteColors">
<x:XData>
<Colors xmlns="">
<Color>Blue</Color>
<Color>Black</Color>
<Color>Green</Color>
<Color>Red</Color>
</Colors>
</x:XData>
</XmlDataProvider>
</StackPanel.Resources>
<TextBlock HorizontalAlignment="Center" FontWeight="Bold">
XML Example
</TextBlock>
<ListBox Width="200" Height="300"
ItemsSource="{Binding Source={StaticResource FavoriteColors},
XPath=/Colors/Color}">
</ListBox>
</StackPanel>

StackPanel 的资源中,我们有一个 XMLDataProvider 对象。x:Key 表示 Binding 对象中用来引用它的名称。在该提供程序中,我们创建了 XML 内联,用作数据绑定的源。在 ListBoxBinding 中,我们将提供程序指定为绑定的 Source。如果某个数据源位于 XAML 文档中,您需要指定该对象是一个静态源,如此处所示。最后,我们使用 XPath 语句指定应该使用 XML 文档中的哪个集合来填充 ListBox。该代码生成图 5 所示的窗体。



图 5. XML 数据绑定

或者,我们可以指定:该提供程序应该使用路径或 URL 来查找用来创建相同窗体的 XML 的源,方法是指定 XMLDataProviderSource 属性。

<XmlDataProvider x:Key="FavoriteColors" Source="D:/Writing/msdn/avalondatabindingpt1/xaml/colors.xml" />

XMLDataProviderSource 属性也可以指向标准 URL,从而使您能够创建到 XML API(如 RSS)的快速访问。

<StackPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel.Resources>
<XmlDataProvider x:Key="MyRSS"
Source="http://adoguy.com/RSS" />
</StackPanel.Resources>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
XML Example
</TextBlock>
<ListBox Width="500" Height="300"
ItemsSource="{Binding Source={StaticResource MyRSS},
XPath=//item/title}">
</ListBox>
</StackPanel>

通过调出到一个 RSS 提要,可以创建一个页面,它在 ListBox 中快速列出我的网络日记中的所有主题,如图 6 所示。



图 6. 我的网络日记的主题列表

使用 ObjectDataProvider

有时需要到 .NET 对象的绑定。这就是引入 ObjectDataProvider 的地方。该数据提供程序使您能够为 .NET 数据类型创建绑定。

例如,我们可以在 .NET 中创建一个简单的字符串集合,如下所示。

public class MyStrings : List
{
public MyStrings()
{
this.Add("Hello");
this.Add("Goodbye");
this.Add("Heya");
this.Add("Cya");
}
}

- 或者 -

Public Class MyStrings
Inherits List(Of String)

Public Sub New()
Me.Add("Hello")
Me.Add("Goodbye")
Me.Add("Heya")
Me.Add("Cya")
End Sub

End Class

也可以在 XAML 文档中使用一条处理指令将 CLR 对象的整个命名空间添加到该文档所支持的类型中,方法是将该命名空间指定为一个 xmlns 声明。例如,我们可以将整个命名空间的类映射到 XAML 中,如下所示。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Source Binding"
xmlns:local="clr-namespace:XamlExamples"
x:Class="XamlExamples.SimpleSource" >
<!-- ... -->
</Window>

要从外部程序集导入类,可以指定一个 xmlns 声明,仅指定程序集名称,如下所示。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Source Binding"
xmlns:sys="clr-namespace:System,assembly=mscorlib"
x:Class="XamlExamples.SimpleSource" >
<!-- ... -->
</Window>

一旦已经导入了类型,就可以使用 ObjectDataProvider 指定来自其中一种类型的数据源。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Source Binding"
xmlns:local="clr-namespace:XamlExamples"
x:Class="XamlExamples.SimpleSource" >
<Window.Resources>
<ObjectDataProvider x:Key="MyStringData"
ObjectType="{x:Type local:MyStrings}" />
</Window.Resources>
<StackPanel>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
Simple Source Example
</TextBlock>
<ListBox Name="theListBox" Width="200" Height="300"
ItemsSource="{Binding Source={StaticResource MyStringData}}"/>
</StackPanel>
</Window>

也可以通过要使用的命名空间和类型指定一个 XAML 元素,来创建资源,如下所示。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Source Binding"
xmlns:local="clr-namespace:XamlExamples"
x:Class="XamlExamples.SimpleSource" >
<Window.Resources>
<local:MyStrings x:Key="MyStringData" />
</Window.Resources>
<StackPanel>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
Simple Source Example
</TextBlock>
<ListBox Name="theListBox" Width="200" Height="300"
ItemsSource="{Binding Source={StaticResource MyStringData}}"/>
</StackPanel>
</Window>

该语法的工作方式就像 ObjectDataSource 一样,只不过更易于使用。既然已经导入了命名空间,我们就可以添加一个引用我们的数据源类的资源了,方法是指定该类的名称(例如, MyStrings)。数据绑定与前面的示例相同,因为 XAML 代码并不关心它是何种数据源,只要是数据源就可以了。

绑定模式

在大多数情况下,您希望绑定是一个双向绑定Binding 对象支持几种模式以支持不同的用例,如表 1 所示。

表 1. 绑定模式
绑定模式说明
TwoWay
双向移动绑定控件或绑定源的改动。(这是默认模式。)
OneWay
仅将改动从源移动到控件。当源发生改动时,绑定控件的数据也相应更改。
OneTime
数据仅在启动时绑定,第一次用数据填充控件后忽略对源的更改。
只需在标记中包括模式即可指定模式,如下所示。

{Binding ElementName=theTextBox, Path=Text, Mode=OneTime}

一种了解双向绑定工作方式的方法是创建一个具有两个文本框的Canvas,一个文本框绑定到另一个文本框。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<Canvas>
<TextBox Name="theTextBox" Text="Hello" />
<TextBox Canvas.Top="25"
Text="{Binding ElementName=theTextBox, Path=Text, Mode=TwoWay}" />
</Canvas>
</Window>

如果将这段代码粘贴到 SDK 附带的 XAMLPad 工具中,您应该注意到,源文本框按照您键入的内容更新绑定的文本框,但是,从绑定控件到源控件的更新仅发生在绑定控件失去焦点时。如果将 Mode 更改为 OneWayOneTime,就会看到这些不同的模式是如何更改绑定的工作方式的。

控制绑定时间

除了模式,您还可以使用UpdateSourceTrigger 指定绑定何时推出更改。您可以指定绑定仅在指定的时间进行更改,方法是指定 UpdateSourceTrigger 类型。

{Binding ElementName=theTextBox, Path=Text, UpdateSourceTrigger=LostFocus}

UpdateSourceTrigger 属性指定何时用改动更新源。这仅对 Mode=TwoWay 绑定(默认方式)有效。表 2 显示 UpdateSourceTrigger 的有效值。

表 2. UpdateSourceTrigger 值
UpdateSourceTrigger说明
Explicit
源仅通过显式调用 BindingExpression.UpdateSource 方法更新。
LostFocus
绑定控件失去焦点时更新源。
PropertyChanged
每次属性更改时都将改动更新到源。这是默认行为。
使用 DataContext

本文要介绍的最后一个概念是如何使用DataContextDataContext 专门用于指定某个容器中的所有控件都将绑定到一个公共对象。

例如,以下是一个示例:我们有一个 Canvas,它将显示 XML 文档中特定节点的值和文本。

<StackPanel
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<StackPanel.Resources>
<XmlDataProvider x:Key="FavoriteColors">
<Colors xmlns="">
<Color ID="1">Blue</Color>
<Color ID="2">Black</Color>
<Color ID="3">Green</Color>
<Color ID="4">Red</Color>
</Colors>
</XmlDataProvider>
</StackPanel.Resources>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
XML DataContext Example
</TextBlock>
<Canvas DataContext="{Binding Source={StaticResource FavoriteColors},
XPath='/Colors/Color[@ID=2]'}">
<TextBlock Text="{Binding XPath=@ID}" />
<TextBlock Canvas.Top="25" Text="{Binding XPath=.}" />
</Canvas>
</StackPanel>

通过将DataContext 设置为 XML 文档(以及一个特定的 XPath 表达式),我们告诉 Canvas:其中所有不包含 Source 的控件都可以使用容器的 DataContext。这样,只需指定 XPath 表达式就能绑定 TextBlock。请注意,每个 TextBlock 中的 XPath 表达式都是相对的 XPath 表达式。这对于对象绑定也一样。

<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Source Binding"
x:Class="XamlExamples.SimpleSource" >
<Window.Resources>
<ObjectDataProvider TypeName="XamlExamples.MyStrings, XamlExamples" x:Key="MyStringData" />
</Window.Resources>
<StackPanel>
<TextBlock HorizontalAlignment="Center"
FontWeight="Bold">
Object DataContext Example
</TextBlock>
<Canvas DataContext="{Binding Source={StaticResource MyStringData}}">
<TextBlock Text="{Binding Path=Length}" />
<TextBlock Canvas.Top="25" Text="{Binding Path=Item[0]}" />
</Canvas>
</StackPanel>
</Window>

使用对象代替 XML 仅仅意味着您将使用 Path 表达式代替 XPath 表达式。



返回页首

我们所处的位置

我们已经了解了在 XAML 中如何用 Binding 对象直接进行数据绑定,既有简化版本又有普通版本。通过利用 XML 或对象数据提供程序,我们可以绑定到应用程序中不同类型的对象。我们还看到如何使用 Binding 对象的 ElementName 语法绑定到其他控件。在本系列的下一部分中,我将向您介绍如何利用该信息并将其绑定到实际的数据库数据,使用您自己的对象或 .NET 数据容器(例如,DataSourcesDataSets)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: