silverlight Binding 详解
这个日记介绍:
创建这种的示例数据源,可以提供给单个对象使用。比例下图的一个Point对象(需要一个X轴和Y轴数据)
下图为创建List Data 数据源:(可以创建class,也可以从XML文件中导入)
创建完数据源,我们需要绑定到界面上。可以在blend中,某个属性后的 小矩形点击后,选择“数据绑定...”,会出来一个面板,上面有三个tab。
第一个tab: 绑定我们刚才那样子用blend 创建出来的,或者导入XML进来的数据源。
第二个tab: 绑定本地其它界面元素
第三个tab: 绑定上下文
手工绑定: 我们也可以用手工编写XAML来绑定。
在blend中,点击某个属性后,选择“自定义表达式”的选项,就可以手工编写XAML绑定语句了。
下面介绍几点类型:
1、Bind Element Property
2、Bind DataContext
3、Bind Data Source
一、Bind Element Property
像刚才那样我们要绑定界面上的一个元素的时候,我们要指定一个 ElementName.来一个图
ElementName是指界面上的哪一个元素。
Path 对应的是这个元素的哪一个属性。
二、Bind DataContext (只能手工编写,不能用工具生成)
如果是在一个已知上下文的范围内去做绑定的话,那我们可以直接这么写: {Binding .}
这么写,表示我们已经绑定到上下文的根节点上了。
三、Bind Data Source
绑定数据源,有两种情况:
1)如下图:
这一种情况可以对我们之前用blend工具生成的数据源来做绑定
2)如下图:(只能手工编写,不能用工具生成)
这个实际上是对父亲节点来做的绑定。来一个例子:
我们把button做成这样:(编辑了外观了的:由一个文本框和一个button组成一个button)
贴上代码:
<Button Height="41" VerticalAlignment="Bottom" Content="Double Click to Submit " Style="{StaticResource ButtonStyle}" Click="OnSubmitInput"/>
模板是这样的:
<Style x:Key="ButtonStyle" TargetType="Button"> <Setter Property="Background" Value="#FF1F3B53"/> <Setter Property="Foreground" Value="#FF000000"/> <Setter Property="Padding" Value="3"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush"> <Setter.Value> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFA3AEB9" Offset="0"/> <GradientStop Color="#FF8399A9" Offset="0.375"/> <GradientStop Color="#FF718597" Offset="0.375"/> <GradientStop Color="#FF617584" Offset="1"/> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> </DoubleAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#F2FFFFFF"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#CCFFFFFF"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#7FFFFFFF"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ColorAnimationUsingKeyFrames Storyboard.TargetName="Background" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#FF6DBDD1"/> </ColorAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="BackgroundAnimation" Storyboard.TargetProperty="Opacity"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> </DoubleAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#D8FFFFFF"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#C6FFFFFF"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#8CFFFFFF"/> </ColorAnimationUsingKeyFrames> <ColorAnimationUsingKeyFrames Storyboard.TargetName="BackgroundGradient" Storyboard.TargetProperty="(Rectangle.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)"> <SplineColorKeyFrame KeyTime="0" Value="#3FFFFFFF"/> </ColorAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="DisabledVisualElement" Storyboard.TargetProperty="Opacity"> <SplineDoubleKeyFrame KeyTime="0" Value=".55"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Focused"> <Storyboard> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="FocusVisualElement" Storyboard.TargetProperty="Opacity"> <SplineDoubleKeyFrame KeyTime="0" Value="1"/> </DoubleAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Unfocused"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <TextBox TextWrapping="Wrap" d:LayoutOverrides="Height" Text="{Binding Tag, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/> <Grid Grid.Column="1"> <Border x:Name="Background" Background="White" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3"> <Grid Margin="1" Background="{TemplateBinding Background}"> <Border x:Name="BackgroundAnimation" Opacity="0" Background="#FF448DCA"/> <Rectangle x:Name="BackgroundGradient"> <Rectangle.Fill> <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0"> <GradientStop Color="#FFFFFFFF" Offset="0"/> <GradientStop Color="#F9FFFFFF" Offset="0.375"/> <GradientStop Color="#E5FFFFFF" Offset="0.625"/> <GradientStop Color="#C6FFFFFF" Offset="1"/> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> </Grid> </Border> <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/> <Rectangle x:Name="DisabledVisualElement" Fill="#FFFFFFFF" RadiusX="3" RadiusY="3" IsHitTestVisible="false" Opacity="0"/> <Rectangle x:Name="FocusVisualElement" Stroke="#FF6DBDD1" StrokeThickness="1" RadiusX="2" RadiusY="2" Margin="1" IsHitTestVisible="false" Opacity="0"/> </Grid> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
可以看到里面有一句这样的:
<TextBox TextWrapping="Wrap" d:LayoutOverrides="Height" Text="{Binding Tag, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
我们要的功能是:在点击那个button的时候,在事件里面可以取到在 TextBox 中输入的内容是什么。
这样的一种需求,我们实际是就是做了这样的绑定
Text="{Binding Tag, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
就是用TextBox的 Text属性,绑定了它的父亲节点,也就是一整个的button 的 Tag 属性,而且是双向绑定。
这样的话,我们在TextBox中做输入的话,对应的整个button 的 Tag属性就会跟着变。
然后在click事件中,我们就可以通过button的 Tag去取得我们刚才输入的值。
private void OnSubmitInput(object sender, System.Windows.RoutedEventArgs e)
{
this.result.Text = (sender as FrameworkElement).Tag as string;
}
为什么我们要用这种绑定呢,而不用前面提到的TemplatedBinding呢,这是因为我们现在这种方式是反向绑定,我们要做的是在button模板中的textbox 的值改变的时候,它的父亲节点的属性改变,而不是那个父亲节点的属性改变后让这个textbox跟着改。
而TemplatedBinding是一个单向的,也就是母改子改。所以它是做不到这个需求的。
四、Binding有多种写法:如下图
最后的tip: 我们在绑定的时候经常会用到转换器,一般都在要 资源里 写XAML来引用转换器。
我们可以不用写XAML代码,而在blend里面操作。
步骤:1、先编写转换器。
2、 在要用到转换器的页面中,打开blend的 data 面板,像最开始说到的那样,创建一个single data ,然后找到转换器。再点OK,blend就会自动在XAML写了引用某个转换器的代码 。 如:
<UserControl.Resources>
<local:NumberToArrowStyleConverter x:Key="NumberToArrowStyleConverter"/>
</UserControl.Resources>
3、接下来你怎么绑定就怎么搞了。