控件模板
控件模板又包括ControlTemplate和ItemsPanelTemplate
ControlTemplate(控件模板)不仅是用于来定义控件的外观、样式, 还可通过控件模板的触发器(ControlTemplate.Triggers)修改控件的行为、响应动画等。
样式定义了一些基础的样式, 背景颜色、字体颜色、边框大小、垂直水平位置等, 除此之外, 下方则有一个Template的对象, 其中则就是ControlTemplate, 可以看到, ControlTemplate定义了一个Border ,然后其中定义了一个内弄呈现的控件, ContentPresenter则主要用于呈现按钮的显示内容主体。
ControlTemplate中的TemplateBinding 的作用
ControlTemplate包含两个重要的属性:
1,VisualTree,该模板的视觉树,其实我们就是使用这个属性来描述控件的外观的
2,Triggers,触发器列表,里面包含一些触发器Trigger,我们可以定制这个触发器列表来使控件对外界的刺激发生反应,比如鼠标经过时文本变成粗体等。
<Button><Button.Template><ControlTemplate><!--定义视觉树--><Grid><Ellipse Name="faceEllipse"Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}" Fill="{TemplateBinding Button.Background}"/><TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Button.Content}"/></Grid><!--定义视觉树_end--> </ControlTemplate></Button.Template>
</Button>
在上面的代码中,我们修改了Button的Template属性,我们定义了一个ControlTemplate,在 < ControlTemplate > ... 之间包含的是模板的视觉树,也就是如何显示控件的外观,我们这里使用了一个Ellipse(椭圆)和一个TextBlock(文本块)来定义控件的外观。
很容易联想到一个问题:控件(Button)的一些属性,比如高度、宽度、文本等如何在新定义的外观中表现出来呢?
我们使用TemplateBinding 将控件的属性与新外观中的元素的属性关联起来Width="{TemplateBinding Button.Width}" ,这样我们就使得椭圆的宽度与按钮的宽度绑定在一起而保持一致,同理我们使用Text="{TemplateBinding Button.Content}"将TextBlock的文本与按钮的Content属性绑定在一起。
除了定义控件的默认外观外,也许我们想还定义当外界刺激我们的控件时,控件外观做出相应的变化,这是我们需要触发器。
<Button Content="test btn" Grid.Column="1" Grid.ColumnSpan="1" Grid.Row="1" Grid.RowSpan="1" ><Button.Template><ControlTemplate><!--定义视觉树--><Grid><Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}" Fill="{TemplateBinding Button.Background}"/><TextBlock Name="txtBlock"Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Button.Content}" /></Grid><!--定义视觉树_end--><!--定义触发器--><ControlTemplate.Triggers><Trigger Property="Button.IsMouseOver" Value="True"><Setter Property="Button.Foreground" Value="Red" /> </Trigger></ControlTemplate.Triggers><!--定义触发器_End--></ControlTemplate></Button.Template></Button>
在上面的代码中注意到 < ControlTemplate .Triggers >... </ControlTemplate.Triggers>之间的部分,我们定义了触发器
如果需要宠用模板,只要把它定义为资源
<Window.Resources><ControlTemplate TargetType="Button" x:Key="ButtonTemplate"><!--定义视觉树--><Grid><Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}" Fill="{TemplateBinding Button.Background}"/><TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Button.Content}" /></Grid><!--定义视觉树_end--><!--定义触发器--><ControlTemplate.Triggers><Trigger Property="Button.IsMouseOver" Value="True"><Setter Property="Button.Foreground" Value="Red" /></Trigger></ControlTemplate.Triggers><!--定义触发器_End--> </ControlTemplate></Window.Resources>
上面的代码将我们原来的模板定义为窗体范围内的资源,其中 TargetType ="Button"指示我们的模板作用对象为Button,这样在整个窗体范围内的按钮都可以使用这个模板了,模板的使用方法也很简单。
<Windowxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ControlTemplateTest" Height="300" Width="300"><Window.Resources><ControlTemplate TargetType="Button" x:Key="ButtonTemplate"><!--定义视觉树--><Grid><Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}" Fill="{TemplateBinding Button.Background}"/><TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Button.Content}" /></Grid><!--定义视觉树_end--><!--定义触发器--><ControlTemplate.Triggers><Trigger Property="Button.IsMouseOver" Value="True"><Setter Property="Button.Foreground" Value="Red" /></Trigger></ControlTemplate.Triggers><!--定义触发器_End--> </ControlTemplate></Window.Resources><Grid ShowGridLines="True"><Grid.ColumnDefinitions><ColumnDefinition Width="0.2*"/><ColumnDefinition Width="0.6*"/><ColumnDefinition Width="0.2*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="0.3*"/><RowDefinition Height="0.3*"/><RowDefinition Height="0.4*"/></Grid.RowDefinitions><Button Content="test btn1" Grid.Column="0"Grid.ColumnSpan="1" Grid.Row="0" Grid.RowSpan="1" /><Button Content="test btn2"Grid.Column="1"Grid.ColumnSpan="1"Grid.Row="1" Grid.RowSpan="1" Template="{StaticResource ButtonTemplate}" /><Button Content="test btn2"Grid.Column="2" Grid.ColumnSpan="1" Grid.Row="2"Grid.RowSpan="1" Template="{StaticResource ButtonTemplate}" /></Grid>
</Window>
如果想加入一些动画效果的话,可以在触发器中,调用一个故事板来达到对事件响应时的动画效果
<EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="faceEllipse"><EventTrigger.Actions><BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/></EventTrigger.Actions>
</EventTrigger>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title="ControlTemplateTest" Height="300" Width="300"><Window.Resources><ControlTemplate TargetType="Button" x:Key="ButtonTemplate"><!--定义视觉树--><Grid><Ellipse Name="faceEllipse" Width="{TemplateBinding Button.Width}" Height="{TemplateBinding Control.Height}" Fill="{TemplateBinding Button.Background}"/><TextBlock Name="txtBlock" Margin="{TemplateBinding Button.Padding}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{TemplateBinding Button.Content}" /></Grid><!--定义视觉树_end--><!--定义动画资源--><ControlTemplate.Resources><Storyboard x:Key="MouseClickButtonStoryboard"><DoubleAnimationUsingKeyFrames Storyboard.TargetName="faceEllipse" Storyboard.TargetProperty="Width" BeginTime="00:00:00"><SplineDoubleKeyFrame KeyTime="00:00:00" Value="50"/><SplineDoubleKeyFrame KeyTime="00:00:00.3" Value="100"/></DoubleAnimationUsingKeyFrames></Storyboard></ControlTemplate.Resources><!--定义动画资源_end--><!--定义触发器--><ControlTemplate.Triggers><Trigger Property="Button.IsMouseOver" Value="True"><Setter Property="Button.Foreground" Value="Red" /></Trigger><EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="faceEllipse"><EventTrigger.Actions><BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/></EventTrigger.Actions> </EventTrigger><EventTrigger RoutedEvent="Mouse.MouseDown" SourceName="txtBlock"><EventTrigger.Actions><BeginStoryboard Storyboard="{StaticResource MouseClickButtonStoryboard}"/></EventTrigger.Actions></EventTrigger></ControlTemplate.Triggers><!--定义触发器_End--></ControlTemplate></Window.Resources><Grid ShowGridLines="True"><Grid.ColumnDefinitions><ColumnDefinition Width="0.2*"/><ColumnDefinition Width="0.6*"/><ColumnDefinition Width="0.2*"/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="0.3*"/><RowDefinition Height="0.3*"/><RowDefinition Height="0.4*"/></Grid.RowDefinitions><Button Content="test btn1" Grid.Column="0" Grid.ColumnSpan="1"Grid.Row="0"Grid.RowSpan="1" /><Button Content="test btn2" Grid.Column="1"Grid.ColumnSpan="1"Grid.Row="1" Grid.RowSpan="1" Template="{StaticResource ButtonTemplate}" /><Button Content="test btn2"Grid.Column="2" Grid.ColumnSpan="1"Grid.Row="2"Grid.RowSpan="1" Template="{StaticResource ButtonTemplate}" /></Grid>
</Window>
mageButton自定义控件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;namespace SoftRGB.Controls
{/// <summary>/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。////// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中:////// xmlns:MyNamespace="clr-namespace:SoftRGB.Controls"///////// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中:////// xmlns:MyNamespace="clr-namespace:SoftRGB.Controls;assembly=SoftRGB.Controls"////// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,/// 并重新生成以避免编译错误:////// 在解决方案资源管理器中右击目标项目,然后依次单击/// “添加引用”->“项目”->[浏览查找并选择此项目]///////// 步骤 2)/// 继续操作并在 XAML 文件中使用控件。////// <MyNamespace:ImageButton/>////// </summary>public class ImageButton : Button{static ImageButton(){DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton)));}#region 依赖属性public static readonly DependencyProperty NormalImageProperty =DependencyProperty.Register("NormalImage", typeof(string), typeof(ImageButton), null);public static readonly DependencyProperty OverImageProperty =DependencyProperty.Register("OverImage", typeof(string), typeof(ImageButton), null);public static readonly DependencyProperty PressedImageProperty =DependencyProperty.Register("PressedImage", typeof(string), typeof(ImageButton), null);public static readonly DependencyProperty DisableImageProperty =DependencyProperty.Register("DisableImage", typeof(string), typeof(ImageButton), null);#endregion#region 属性/// <summary>/// 正常状态下显示的图片/// </summary>public string NormalImage{get { return (string)GetValue(NormalImageProperty); }set { SetValue(NormalImageProperty, value); }}/// <summary>/// 鼠标滑过状态下显示的图片/// </summary>public string OverImage{get { return (string)GetValue(OverImageProperty); }set { SetValue(OverImageProperty, value); }}/// <summary>/// 鼠标点击状态下显示的图片/// </summary>public string PressedImage{get { return (string)GetValue(PressedImageProperty); }set { SetValue(PressedImageProperty, value); }}/// <summary>/// 禁用状态下显示的图片/// </summary>public string DisableImage{get { return (string)GetValue(DisableImageProperty); }set { SetValue(DisableImageProperty, value); }}#endregion}
}
<Style TargetType="{x:Type local:ImageButton}"><Setter Property="Background" Value="Transparent"/><Setter Property="FocusVisualStyle" Value="{x:Null}"/><Setter Property="VerticalAlignment" Value="Center"/><Setter Property="HorizontalAlignment" Value="Center"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type local:ImageButton}"><Grid x:Name="Root" Background="Transparent"><VisualStateManager.VisualStateGroups><VisualStateGroup x:Name="CommonStates"><VisualState x:Name="Normal"><Storyboard><ObjectAnimationUsingKeyFrames Storyboard.TargetName="NormalUI" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0"Value="{StaticResource Visible}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualState x:Name="MouseOver"><Storyboard><ObjectAnimationUsingKeyFrames Storyboard.TargetName="OverUI" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualState x:Name="Pressed"><Storyboard><ObjectAnimationUsingKeyFrames Storyboard.TargetName="PressedUI" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualState x:Name="Disabled"><Storyboard><ObjectAnimationUsingKeyFrames Storyboard.TargetName="DisableUI" Storyboard.TargetProperty="Visibility"><DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource Visible}"/></ObjectAnimationUsingKeyFrames></Storyboard></VisualState></VisualStateGroup></VisualStateManager.VisualStateGroups><Border Background="{TemplateBinding Background}"BorderBrush="{TemplateBinding BorderBrush}"BorderThickness="{TemplateBinding BorderThickness}"><Grid><Image x:Name="NormalUI" Source="{Binding NormalImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/><Image x:Name="OverUI" Source="{Binding OverImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/><Image x:Name="PressedUI" Source="{Binding PressedImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/><Image x:Name="DisableUI" Source="{Binding DisableImage, RelativeSource={RelativeSource TemplatedParent}}" Visibility="Collapsed"/><ContentPresenter x:Name="ContentPresenter" Margin="{TemplateBinding Padding}" ContentTemplate="{TemplateBinding ContentTemplate}"VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/></Grid></Border></Grid></ControlTemplate></Setter.Value></Setter>
</Style>
数据模板
数据模板是一段如何显示绑定在VM对象的XAML代码。数据模板可以包含任意元素的组合,基于Binding来显示不同的信息。
在实际的开发中数据模板的应用场景很多,同样一个控件可以根据不同的绑定源,根据以设置好的数据模板可以显示对应的不同的内容。
- 1.Grid这种列表表格中修改Cell的数据格式, CellTemplate可以修改单元格的展示数据的方式。
- 2.针对列表类型的控件, 例如树形控件,下拉列表,列表控件, 可以修改其中的ItemTemplate。
- 3.修改ContentTemplate, 例UserControl控件的数据展现形式。
CellTemplate 模板
实现一个DataGrid 展示一个普通的数据标, 同时新增一列CellTemplate添加两个自定义的按钮
<DataGrid Name="gd" AutoGenerateColumns="False" CanUserSortColumns="True" CanUserAddRows="False"><DataGrid.Columns><DataGridTextColumn Binding="{Binding UserName}" Width="100" Header="学生姓名"/><DataGridTextColumn Binding="{Binding ClassName}" Width="100" Header="班级名称"/><DataGridTextColumn Binding="{Binding Address}" Width="200" Header="地址"/><DataGridTemplateColumn Header="操作" Width="100" ><DataGridTemplateColumn.CellTemplate><DataTemplate><StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left"><Button Content="编辑"/><Button Margin="8 0 0 0" Content="删除" /></StackPanel></DataTemplate></DataGridTemplateColumn.CellTemplate></DataGridTemplateColumn></DataGrid.Columns></DataGrid>
完成操作, 然后后台进行该DataGrid进行绑定数据, 查询绑定后的效果。
List<Student> students = new List<Student>();students.Add(new Student() { UserName = "小王", ClassName = "高二三班", Address = "广州市" });students.Add(new Student() { UserName = "小李", ClassName = "高三六班", Address = "清远市" });students.Add(new Student() { UserName = "小张", ClassName = "高一一班", Address = "深圳市" });students.Add(new Student() { UserName = "小黑", ClassName = "高一三班", Address = "赣州市" });gd.ItemsSource = students;
最终的效果, 在数据的表格最后一列, 将会在一列中分别生成 两个普通按钮。
ItemTemplate
在列表的控件中, 常常会出现一些需求, 类似在下拉控件或树控件中添加一个 CheckBox选择框, 一个图标或图片, 这个时候, 我们就可以利用自定义的DataTemplate 来实现这个功能,
接下来, 用一个示例来简单演示其功能, 同样, 该例子演示利用 ListBox 和 ComboBox来绑定一个 颜色代码列表, 同时展示其颜色。
<Window.Resources><DataTemplate x:Key="comTemplate"><StackPanel Orientation="Horizontal" Margin="5,0"><Border Width="10" Height="10" Background="{Binding Code}"/><TextBlock Text="{Binding Code}" Margin="5,0"/></StackPanel></DataTemplate></Window.Resources><Grid><StackPanel Orientation="Horizontal" HorizontalAlignment="Center"><ComboBox Name="cob" Width="120" Height="30" ItemTemplate="{StaticResource comTemplate}"/><ListBox Name="lib" Width="120" Height="100" Margin="5,0" ItemTemplate="{StaticResource comTemplate}"/></StackPanel></Grid>
上面的代码中, 定义了一个DataTemplate , 顶一个 长宽10px的border用于显示颜色代码, 绑定到Border背景颜色上, 定义了一个TextBlock用于展示颜色的代码。
List<Color> ColorList = new List<Color>();ColorList.Add(new Color() { Code = "#FF8C00" });ColorList.Add(new Color() { Code = "#FF7F50" });ColorList.Add(new Color() { Code = "#FF6EB4" });ColorList.Add(new Color() { Code = "#FF4500" });ColorList.Add(new Color() { Code = "#FF3030" });ColorList.Add(new Color() { Code = "#CD5B45" });cob.ItemsSource = ColorList;lib.ItemsSource = ColorList;
ItemsControl
定义ItemsControl 主要分两个步骤:
1.设置ItemsPanel容器, 用于容纳列表的最外层容器
2.定义子项的DataTemplate
<ItemsControl Name="ic"><ItemsControl.ItemsPanel><ItemsPanelTemplate><WrapPanel Orientation="Horizontal"/></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><Button Width="50" Height="50" Content="{Binding Code}"/></DataTemplate></ItemsControl.ItemTemplate></ItemsControl>
上面代码中, 定义了一个WarpPanel 容器为ItemControl的 最外层容器, 子项数据模板则绑定了一个按钮, 后台代码绑定几条数据, 查看其效果: 横排排列五个按钮, 内容分别是 1~6.
List<Test> tests = new List<Test>();tests.Add(new Test() { Code = "1" });tests.Add(new Test() { Code = "2" });tests.Add(new Test() { Code = "3" });tests.Add(new Test() { Code = "4" });tests.Add(new Test() { Code = "6" });ic.ItemsSource = tests;
绑定
在winform中, 我们常常会用到各种类型的赋值, 例如:
- button1.Text="Hello";
- label.Text="Hello";
- ...
类似这种赋值操作, 我们之所以不称之为绑定, 主要原因是因为他们大多数操作都是一次性的, 无论是数据还是按钮本身发生变化,对两者而言都是不可见的。
而绑定的概念则侧重于: 两者的关联,协议与两者之间的影响。
- Text=
- {Binding }: Binding的声明语法, 一对尖括号,开头声明以Binding 开始。
- ElementName= : 该声明意为, 设置元素的名称
- Path: 设置关联元素的位置,上例中设置为元素的value属性。
在WPF中绑定的模式又分为五种:
1.OneWay(单向绑定) : 当源属性发生变化更新目标属性, 类似上面的例子中, 滑动变化更新文本的数据。
2.TwoWay(双向绑定) : 当源属性发生变化更新目标属性, 目标属性发生变化也更新源属性。
与单向绑定的区别可以理解为, 前者只能打你,被打者不能还手, 双向绑定的意思则是: 你敢打我一巴掌,我也能回你一巴掌
3.OneTime(单次模式) : 根据第一次源属性设置目标属性, 在此之后所有改变都无效。
如第一次绑定了数据源为0, 那么无论后面如何改变 2、3、4... 都无法更新到目标属性上。
4.OneWayToSource : 和OneWay类型, 只不过整个过程倒置。
5.Default : 既可以是双向,也可以是单项, 除非明确表明某种模式, 否则采用该默认绑定
绑定到非元素上
https://docs.microsoft.com/zh-cn/?WT.mc_id=DT-MVP-5003986
微软开发者平台:
https://developer.microsoft.com/en-us/?WT.mc_id=DT-MVP-5003986
什么是绑定(Binding)?
在winform中, 我们常常会用到各种类型的赋值, 例如:
- button1.Text="Hello";
- label.Text="Hello";
- ...
类似这种赋值操作, 我们之所以不称之为绑定, 主要原因是因为他们大多数操作都是一次性的, 无论是数据还是按钮本身发生变化,对两者而言都是不可见的。
而绑定的概念则侧重于: 两者的关联,协议与两者之间的影响。
首先, 从一个简单的例子来理解什么是绑定。
- 创建一个滑块控件, 并且希望在滑动的过程中, 把值更新到另外一个静态文本上。代码如下:
在winform中, 我们常规的做法会给滑块创建一个值改变事件,同时将滑块的值赋值给文本。
接下来, 我只需要在静态文本中添加一小段绑定的声明,即可完整原本很复杂的操作:
- Text=
- {Binding }: Binding的声明语法, 一对尖括号,开头声明以Binding 开始。
- ElementName= : 该声明意为, 设置元素的名称
- Path: 设置关联元素的位置,上例中设置为元素的value属性。
那么该如何理解整句话的意义, 翻译: 静态文本TextBlock的Text属性将通过绑定的方式关联到元素名'slider'的value属性上。
效果图所示:
可以看到,在滑块不断的滑动过程中, TextBlock也在不断的发生变化, 说明TextBlock已经得到了滑动滑动过程中的值变化, 这种关联, 我们称之为绑定, 在WPF当中, 绑定又分很多种, 而上面这种则是通过元素绑定的方式。
理解了基础的绑定之后,然后就是理解绑定的模式。
绑定的模式就类似我们商业中的合作, 是一次性回报还是持续获益, 是否可以单方面终止, 是否具有投票权等, 在WPF中绑定的模式又分为五种:
- OneWay(单向绑定) : 当源属性发生变化更新目标属性, 类似上面的例子中, 滑动变化更新文本的数据。示例:
效果:
- TwoWay(双向绑定) : 当源属性发生变化更新目标属性, 目标属性发生变化也更新源属性。
- 与单向绑定的区别可以理解为, 前者只能打你,被打者不能还手, 双向绑定的意思则是: 你敢打我一巴掌,我也能回你一巴掌。示例:
效果:
- 与单向绑定的区别可以理解为, 前者只能打你,被打者不能还手, 双向绑定的意思则是: 你敢打我一巴掌,我也能回你一巴掌。示例:
- OneTime(单次模式) : 根据第一次源属性设置目标属性, 在此之后所有改变都无效。
- 如第一次绑定了数据源为0, 那么无论后面如何改变 2、3、4... 都无法更新到目标属性上。示例:
效果:
- 如第一次绑定了数据源为0, 那么无论后面如何改变 2、3、4... 都无法更新到目标属性上。示例:
- OneWayToSource : 和OneWay类型, 只不过整个过程倒置。示例:
效果:
- Default : 既可以是双向,也可以是单项, 除非明确表明某种模式, 否则采用该默认绑定