WPF数据绑定---Binding学习笔记(一)
WPF里分三种Binding:Binding, PriorityBinding,MultiBinding,这三种Binding的基类都是BindingBase,而BindingBase又继承于MarkupExtension
1.Binding 中 绑定到其他控件 ElementName
Binding 绑定是 模式设置 Mode
2. source = {binding} 和source = {binding RelativeSource={RelativeSource self},Path=DataContext}效果相同
理解:{binding} 不设定明确的绑定的source,这样binding就去从本控件类为开始根据可视树的层次结构自下而上查找不为空的Datacontext属性的值。
{binding RelativeSource={RelativeSource self},Path=DataContext}中RelativeSource self的含义为绑定的source为控件自身,这样binding 就绑定了自身控件的Datacontext。
<StackPanel Orientation="Vertical" DataContext="上海世博会"> <Border BorderThickness="2" BorderBrush="BlueViolet"> <TextBlock Text="{Binding}"></TextBlock> </Border> <Border BorderThickness="2" BorderBrush="BlueViolet"> <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}"></TextBlock> </Border> </StackPanel>
RelativeSource 可以用来指定binding的source和binding的target之间的位置关系。
RelativeSource的四种模式:
1.RelativeSource Mode=Self 模式:
目标元素应用作此绑定的源。当要将元素的一个属性绑定到同一元素的另一个属性时。
<StackPanel Orientation="Vertical" DataContext="上海世博会" Name="stackPanel"> <Border BorderThickness="2" BorderBrush="BlueViolet"> <TextBlock Name="绑定自己的属性" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}"></TextBlock> </Border> </StackPanel>
效果 但是把 Xmal 改成如下时 !此时Path=Name 并不会去容器的Name 属性 寻找 StackPanel Name=“stackPanel”
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}"></TextBlock>
此时为空
但是:当Path=DataContext 就会出现另一个效果
<StackPanel Orientation="Vertical" DataContext="上海世博会" Name="stackPanel"> <Border BorderThickness="2" BorderBrush="BlueViolet"> <TextBlock Name="绑定自己的属性" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}" DataContext="北京欢迎你"></TextBlock> </Border> </StackPanel>
把 DataContext="北京欢迎你" 。删除后 Path=DataContext 就会向上寻找 DataContext 只到找到为止。
<TextBlock Name="绑定自己的属性" Text="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext}"></TextBlock>1.Self模式
2.PreviousData 模式:
允许您绑定所显示数据项列表中以前的数据项(不是包含数据项的控件)。源码:
<Window x:Class="WPFBindingDemo.RelativeSourceWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WPFBindingDemo" xmlns:collection="clr-namespace:System.Collections;assembly=mscorlib" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="RelativeSourceWindow" Height="300" Width="300"> <Window.Resources> <collection:ArrayList x:Key="cillectionkey"> <sys:String>上海</sys:String> <sys:String>北京</sys:String> <sys:String>天津</sys:String> <sys:String>南京</sys:String> </collection:ArrayList> </Window.Resources> <StackPanel Orientation="Vertical"> <ListBox ItemsSource="{StaticResource ResourceKey=cillectionkey}"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding}"></TextBlock> <TextBlock Text="{Binding RelativeSource={RelativeSource Mode=PreviousData}}" Margin="15 0 0 0"></TextBlock> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </StackPanel> </Window>
效果图:
3.TemplatedParent模式
在其中应用 ControlTemplate 的控件是此绑定的源。这一点可用来在模板级别应用绑定中的验证错误信息。
<StackPanel Orientation="Vertical"> <Button Width="150" Height="35" Margin="0 20 0 0" Content="TemplateBinding"> <Button.Background> <LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5"> <GradientStop Color="BlueViolet" Offset="0.0"></GradientStop> <GradientStop Color="WhiteSmoke" Offset="0.5"></GradientStop> <GradientStop Color="BlueViolet" Offset="1.0"></GradientStop> </LinearGradientBrush> </Button.Background> <Button.Template> <ControlTemplate> <Border BorderThickness="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=BorderThickness}" Background="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Background}"> <TextBlock Text="{TemplateBinding Button.Content}"></TextBlock> </Border> </ControlTemplate> </Button.Template> </Button> </StackPanel>
效果图:
TemplateBinding和Binding的区别
TemplateBinding是为了某个特定场景优化出来的数据绑定版本--需要把ControlTemplate里面的某个Property绑定到应用该ControlTemplate的控件的对应Property上。
TemplateBinding 用法:
在属性赋值中直接的用法:
<object property="{TemplateBinding targetProperty}" .../>
在模板或样式中用Setter属性的用法:
<Setter Property="propertyName" Value="{TemplateBinding targetProperty}" .../>
两者区别:
1. Binding比TemplateBinding更加灵活强大,但是开销也更大。TemplateBinding在使用场景有限制,但是效率较高。Template非常类似{Binding RelativeSource={RelativeSource TemplatedParent}}构造的Binding。
2. TemplateBinding同样允许我们定义Converter和ConverterParameter,在一定程度上加强了TemplateBinding的应用功能和范围.
3. 最重要的区别:TemplateBinding仅仅支持单向的数据绑定,从应用Template的控件到Template(from templated control to template)。如果我们需要反向或者双向的绑定,唯一的选择就是应用Binding和RelativeSource。
使用时如何选择:
如果我们需要一个单向的绑定,使数据从应用template的控件(templated parent)到template,我们就该使用高效而简单的TemplateBinding,其他情况下都使用Binding。
4.FindAncestor模式
FindAncestor:引用数据绑定元素父链中的上级。 您可以使用它绑定到特定类型或其子类的上级。 如果您要指定 AncestorType 和/或 AncestorLevel,可以使用此模式
AncestorType 获取或设置要查找的上级节点的类型。如果未显式设置 Mode 属性,那么设置 AncestorType 或 AncestorLevel 属性将把 Mode 属性值隐式锁定为 FindAncestor。
<StackPanel Orientation="Vertical" Margin="0 20 0 0"> <Button Background="BlanchedAlmond"> <StackPanel> <Button Margin="20 0 0 0" HorizontalAlignment="Left" Background="RoyalBlue"> <StackPanel> <Button Margin="{Binding Path=Margin, RelativeSource={RelativeSource AncestorType=Button, Mode=FindAncestor}}" Content="上海世博会"></Button> <Button Content="北京奥运会"></Button> </StackPanel> </Button> </StackPanel> </Button> </StackPanel>
效果图:
绑定二 xaml 源码
<StackPanel Orientation="Vertical" Margin="0 20 0 0"> <Button Background="BlanchedAlmond"><!--AncestorLevel=2--> <StackPanel> <Button Margin="20 0 0 0" HorizontalAlignment="Left" Background="RoyalBlue"><!--AncestorLevel=1--> <StackPanel> <Button Margin="{Binding Path=Margin, RelativeSource={RelativeSource AncestorType=Button, Mode=FindAncestor}}" Content="上海世博会"></Button> <Button Content="北京奥运会" Background="{Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type Button},
AncestorLevel=1, Mode=FindAncestor}}"> </Button> </StackPanel> </Button> </StackPanel> </Button> </StackPanel>
效果图: AncestorLevel=1 修改成 AncestorLevel=2 背景设为
<Button Content="北京奥运会" Background="{Binding Path=Background, RelativeSource={RelativeSource AncestorType={x:Type Button}, AncestorLevel=2, Mode=FindAncestor}}"></Button>
效果图: