WPF/Silverlight2.0 Binding(数据绑定)机制详解
何为数据绑定
在WPF技术中控件基类(FrameworkElement、FrameworkContentElement)中DataContext属性实现了绑定机制,在XAML中也支持此机制。当一个控件的DataContext发生变化时,其子控件的DataContext也会继承父控件的DataContext(前提是这个子控件没有另外赋值)。子控件的属性获取数据源中的数据,支持XAML通过Binding标记获取数据源中的值。数据源更新时刷新其每个子控件中的数据更新,实现一呼百应的效果!
Binding绑定标记
XAML处理器支持绑定机制的语法,以{Binding PropertyName=Value}格式出现。其中PropertyName基本分为“数据源指定标记、读取数据源标记、附加选项标记”,Value可以使用其它标记获取特殊的值。绑定表达式中可以使用数据源标记、读取数据源标记、附加选项标记组合使用,也可以使用父控件绑定数据源,子控件继承父控件的数据源并进行绑定。
语法
<TextBox Name="theTextBox" />
<TextBlock Text="{Binding ElementName=theTextBox, Path=Text}"/>
同于
<TextBox Name="theTextBox" />
<TextBlock>
<TextBlock.Text>
<Binding ElementName="theTextBox" Path="Text" />
</TextBlock.Text>
</TextBlock>
数据源指定标记
Source属性:通过其它扩展标记制定任何类型的对象实例为数据源,可以使用StaticResource等标记设置。例如:“{Binding Source={StaticResource xKeyElement}, XPath=//item}”,xKeyElement是XMLDataProvider的对象,意思是获取以xKeyElement中所有以item为标签节点的数据为数据源。
ElementName属性:制定当前XAML文档中任何以(x:Name)名称为ElementName值的对象为数据源。例如:“{Binding ElementName=ListBox1, Path=SelectedItem}”,意思是把ListBox1的SelectedItem属性为当前控件的数据源。
RelativeSource属性:相对数据源,使用RelativeSource可以制定与自身相关联的对象为数据源。例如:“RelativeSource={RelativeSource Self}}”,读者注意“中间的是RelativeSource{}是一个扩展标记,而外面的RelativeSource={}是Binding标记的属性”。这段实例代码的意思是获取自身为数据源。
获取数据源标记
Path属性:于“数据源指定标记”一起使用,获取数据源中的成员(属性)。如果数据源对象继承了ICustomeTypeDescriptor接口,将会从接口中获取属性值,否则使用类反射获取。例如:Text="{Binding ElementName=ListBox1, Path=Items[0].Text}",其中ElementName设置数据源,获取ListBox1.Items[0].Text并赋予给Text属性。
XPath属性:于“数据源指定标记”一起使用,通过XPath检索XML数据源内容。
官方实例代码段:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Cornsilk">
<StackPanel.Resources>
<XmlDataProvider x:Key="InventoryData" XPath="Inventory/Books">
<x:XData>
<Inventory xmlns="">
<Books>
<Book ISBN="0-7356-0562-9" Stock="in" Number="9">
<Title>XML in Action</Title>
<Summary>XML Web Technology</Summary>
</Book>
<Book ISBN="0-7356-1370-2" Stock="in" Number="8">
<Title>Programming Microsoft Windows With C#</Title>
<Summary>C# Programming using the .NET Framework</Summary>
</Book>
<Book ISBN="0-7356-1288-9" Stock="out" Number="7">
<Title>Inside C#</Title>
<Summary>C# Language Programming</Summary>
</Book>
<Book ISBN="0-7356-1377-X" Stock="in" Number="5">
<Title>Introducing Microsoft .NET</Title>
<Summary>Overview of .NET Technology</Summary>
</Book>
<Book ISBN="0-7356-1448-2" Stock="out" Number="4">
<Title>Microsoft C# Language Specifications</Title>
<Summary>The C# language definition</Summary>
</Book>
</Books>
<CDs>
<CD Stock="in" Number="3">
<Title>Classical Collection</Title>
<Summary>Classical Music</Summary>
</CD>
<CD Stock="out" Number="9">
<Title>Jazz Collection</Title>
<Summary>Jazz Music</Summary>
</CD>
</CDs>
</Inventory>
</x:XData>
</XmlDataProvider>
</StackPanel.Resources>
<TextBlock FontSize="18" FontWeight="Bold" Margin="10"
HorizontalAlignment="Center">XML Data Source Sample</TextBlock>
<ListBox
Width="400" Height="300" Background="Honeydew">
<ListBox.ItemsSource>
<Binding Source="{StaticResource InventoryData}"
XPath="*[@Stock='out'] | *[@Number>=8 or @Number=3]"/>
</ListBox.ItemsSource>
<!--Alternatively, you can do the following. -->
<!--<ListBox Width="400" Height="300" Background="Honeydew"
ItemsSource="{Binding Source={StaticResource InventoryData},
XPath=*[@Stock\=\'out\'] | *[@Number>\=8 or @Number\=3]}">-->
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="12" Foreground="Red">
<TextBlock.Text>
<Binding XPath="Title"/>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
附加选项标记
Model属性:BindingMode枚举值,设置数据绑定的依赖机制。
OneWay 仅当源属性发生更改时更新目标属性。
OneTime 仅当应用程序启动时或 DataContext 进行更改时更新目标属性。
OneWayToSource 在目标属性更改时更新源属性。
默认为双向绑定。例如:{Binding Path=Value, Mode=OneTime},当数据源更新时当前控件重新绑定。