首页 > WPF and Silverlight 学习笔记(二十):WPF数据绑定概述

WPF and Silverlight 学习笔记(二十):WPF数据绑定概述

WPF数据绑定为应用程序提供了一种表示数据和与数据交互的简单而又一致的方法。元素能够以公共语言运行库 (CLR) 对象和 XML 的形式绑定到各种数据源中的数据。

一、数据绑定的基本概念:

数据绑定涉及到两个方面:一个是绑定源,再一个是绑定目标。绑定源即控件绑定所使用的源数据,绑定目标即数据显示的控件。

1、对于绑定源,在WPF可以是以下四种:

  • CLR对象:可以绑定到CLR类的公开的属性、子属性、索引器上
  • ADO.Net对象:例如DataTable、DataView等
  • XML文件:使用XPath进行解析
  • DependencyObject:绑定到其依赖项属性上,即控件绑定控件

2、对于绑定目标,必须是WPF中的DependencyObject,将数据绑定到其依赖项属性上。

DataBinding1

二、绑定的基本方式

根据数据流的方向,WPF中的数据绑定分为以下四种:

DataBinding2

  • OneWay 绑定导致对源属性的更改会自动更新目标属性,但是对目标属性的更改不会传播回源属性。此绑定类型适用于绑定的控件为隐式只读控件的情况。例如,您可能绑定到如股票行情自动收录器这样的源,或许目标属性没有用于进行更改的控件接口(如表的数据绑定背景色)。如果无需监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的系统开销。

  • TwoWay 绑定导致对源属性的更改会自动更新目标属性,而对目标属性的更改也会自动更新源属性。此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案。大多数属性都默认为 OneWay 绑定,但是一些依赖项属性(通常为用户可编辑的控件的属性,如 TextBox 的 Text 属性和 CheckBox 的 IsChecked 属性)默认为 TwoWay 绑定。确定依赖项属性绑定在默认情况下是单向还是双向的编程方法是:使用 GetMetadata 获取属性的属性元数据,然后检查 BindsTwoWayByDefault 属性的布尔值。

  • OneWayToSource 与 OneWay 绑定相反;它在目标属性更改时更新源属性。一个示例方案是您只需要从 UI 重新计算源值的情况。

  • OneTime绑定 ,该绑定会导致源属性初始化目标属性,但不传播后续更改。这意味着,如果数据上下文发生了更改,或者数据上下文中的对象发生了更改,则更改会反映在目标属性中。如果您使用的数据的当前状态的快照适于使用,或者这些数据是真正静态的,则适合使用此绑定类型。如果要使用源属性中的某个值初始化目标属性,并且事先不知道数据上下文,则也可以使用此绑定类型。此绑定类型实质上是 OneWay 绑定的简化形式,在源值不更改的情况下可以提供更好的性能。

每个依赖项属性的默认值都不同。一般情况下,用户可编辑控件属性(例如文本框和复选框的属性)默认为双向绑定,而多数其他属性默认为单向绑定。确定依赖项属性绑定在默认情况下是单向还是双向的编程方法是:使用 GetMetadata 来获取属性的属性元数据,然后检查 BindsTwoWayByDefault 属性的布尔值。

三、实现数据源更改影响目标更改

如果要实现数据源更改时,改变目标的值(即上图中的OneWay方式及TwoWay方式的由绑定源到绑定目标方向的数据绑定),需使数据源对象实现System.ComponentModel命名空间的INotifyPropertyChanged接口。INotifyPropertyChanged接口中定义了一个PropertyChanged事件,在某属性值发生变化时引发此事件,即可通知绑定目标更改其显示的值。例如:

   1: using System.ComponentModel;
   2:  
   3: namespace BasicWPFDataBinding
   4: { 
   5:     public class MyData : INotifyPropertyChanged
   6:     { 
   7:         #region INotifyPropertyChanged Members
   8:         public event PropertyChangedEventHandler PropertyChanged;
   9:         #endregion
  10:  
  11:         public MyData()
  12:         { 
  13:             Name = "Tom";
  14:         }
  15:  
  16:         private string _Name;
  17:         public string Name
  18:         { 
  19:             set
  20:             { 
  21:                 _Name = value;
  22:  
  23:                 if (PropertyChanged != null)
  24:                 { 
  25:                     // 引发PropertyChanged事件,
  26:                     // PropertyChangedEventArgs构造方法中的参数字符串表示属性名
  27:                     PropertyChanged(this,new PropertyChangedEventArgs("Name"));
  28:                 }
  29:             } 
  30:             get
  31:             { 
  32:                 return _Name;
  33:             }
  34:         }
  35:     }
  36: }

 

四、实现绑定目标的值更改影响绑定源的值

若实现实现绑定目标的值更改影响绑定源的值(即上图中TwoWay的由绑定目标到绑定源方向,及OneWayToSource),可以设置相应控件绑定时的UpdateSourceTrigger的值,其值有三种:

  • PropertyChanged:当绑定目标属性更改时,立即更新绑定源。
  • LostFocus:当绑定目标元素失去焦点时,更新绑定源。
  • Explicit:仅在调用 UpdateSource 方法时更新绑定源。

多数依赖项属性的UpdateSourceTrigger 值的默认值为 PropertyChanged,而 Text 属性的默认值为 LostFocus。

例如:

   1: <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

五、示例:

下面的示例使用第3节中的MyData类作为数据源,演示基于4种绑定方式的执行效果:

DataBinding3

XAML代码如下:

   1: <Window x:Class="BasicWPFDataBinding.WinBasicBinding"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:c="clr-namespace:BasicWPFDataBinding"
   5:     Title="WinBasicBinding" Height="360" Width="360">
   6:     <Grid>
   7:         <Grid.ColumnDefinitions>
   8:             <ColumnDefinition/>
   9:             <ColumnDefinition/>
  10:         Grid.ColumnDefinitions>
  11:         <Grid.RowDefinitions>
  12:             <RowDefinition/>
  13:             <RowDefinition/>
  14:         Grid.RowDefinitions>
  15:         <StackPanel Grid.Row="0" Grid.Column="0" x:Name="panelOneTime">
  16:             <StackPanel.Resources>
  17:                 <c:MyData x:Key="myDataSourceA" />
  18:             StackPanel.Resources>
  19:             <StackPanel.DataContext>
  20:                 <Binding Source="{StaticResource myDataSourceA}" />
  21:             StackPanel.DataContext>
  22:             <TextBlock Text="OneTime Binding" />
  23:             <TextBox Margin="5" Text="{Binding Path=Name, Mode=OneTime}" />
  24:             <Button Margin="5" Content="Change Name" 
  25:                     x:Name="btnOneTimeBindingChange" Click="btnOneTimeBindingChange_Click" />
  26:             <Button Margin="5" Content="Get Name" 
  27:                     x:Name="btnOnTimeBindingGet" Click="btnOnTimeBindingGet_Click" />
  28:         StackPanel>
  29:         <StackPanel Grid.Row="0" Grid.Column="1" x:Name="panelOneWay">
  30:             <StackPanel.Resources>
  31:                 <c:MyData x:Key="myDataSourceB" />
  32:             StackPanel.Resources>
  33:             <StackPanel.DataContext>
  34:                 <Binding Source="{StaticResource myDataSourceB}" />
  35:             StackPanel.DataContext>
  36:             <TextBlock Text="OneWay Binding" />
  37:             <TextBox Margin="5" 
  38:                      Text="{Binding Path=Name, Mode=OneWay}" />
  39:             <Button Margin="5" Content="Change Name" 
  40:                     x:Name="btnOneWayeBindingChange" Click="btnOneWayeBindingChange_Click" />
  41:             <Button Margin="5" Content="Get Name" 
  42:                     x:Name="btnOneWayBindingGet" Click="btnOneWayBindingGet_Click" />
  43:         StackPanel>
  44:         <StackPanel Grid.Row="1" Grid.Column="0" x:Name="panelTwoWay">
  45:             <StackPanel.Resources>
  46:                 <c:MyData x:Key="myDataSourceC" />
  47:             StackPanel.Resources>
  48:             <StackPanel.DataContext>
  49:                 <Binding Source="{StaticResource myDataSourceC}" />
  50:             StackPanel.DataContext>
  51:             <TextBlock Text="TwoWay Binding" />
  52:             <TextBox Margin="5" 
  53:                      Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
  54:             <Button Margin="5" Content="Change Name" 
  55:                     x:Name="btnTwoWayBindingChange" Click="btnTwoWayBindingChange_Click" />
  56:             <Button Margin="5" Content="Get Name" 
  57:                     x:Name="btnTwoWayBindingGet" Click="btnTwoWayBindingGet_Click" />
  58:             <TextBlock Margin="5" 
  59:                        Text="{Binding Path=Name, Mode=OneWay}" />
  60:         StackPanel>
  61:         <StackPanel Grid.Row="1" Grid.Column="1" x:Name="panelOneWayToSource">
  62:             <StackPanel.Resources>
  63:                 <c:MyData x:Key="myDataSourceD" />
  64:             StackPanel.Resources>
  65:             <StackPanel.DataContext>
  66:                 <Binding Source="{StaticResource myDataSourceD}" />
  67:             StackPanel.DataContext>
  68:             <TextBlock Text="OneWayToSource Binding" />
  69:             <TextBox Margin="5" 
  70:                      Text="{Binding Path=Name, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
  71:             <Button Margin="5" Content="Change Name" 
  72:                     x:Name="btnOneWayToSourceBindingChange" Click="btnOneWayToSourceBindingChange_Click" />
  73:             <Button Margin="5" Content="Get Name" 
  74:                     x:Name="btnOneWayToSourceBindingGet" Click="btnOneWayToSourceBindingGet_Click" />
  75:             <TextBlock Margin="5" 
  76:                        Text="{Binding Path=Name, Mode=OneWay}" />
  77:         StackPanel>
  78:     Grid>
  79: Window>

代码文件如下:

   1: using System.Windows;
   2:  
   3: namespace BasicWPFDataBinding
   4: { 
   5:     /// <summary>
   6:     /// Interaction logic for WinBasicBinding.xaml
   7:     /// summary>
   8:     public partial class WinBasicBinding : Window
   9:     { 
  10:         public WinBasicBinding()
  11:         { 
  12:             InitializeComponent();
  13:         }
  14:  
  15:         #region OneTime绑定
  16:         private void btnOneTimeBindingChange_Click(object sender, RoutedEventArgs e)
  17:         { 
  18:             MyData source = (MyData)(panelOneTime.DataContext);
  19:             source.Name = "Jerry";
  20:  
  21:             MessageBox.Show(
  22:                 "myData.Name has been changed to Jerry",
  23:                 "System Information",
  24:                 MessageBoxButton.OK,
  25:                 MessageBoxImage.Information);
  26:         }
  27:  
  28:         private void btnOnTimeBindingGet_Click(object sender, RoutedEventArgs e)
  29:         { 
  30:             MyData source = (MyData)(panelOneTime.DataContext);
  31:  
  32:             string name = source.Name;
  33:  
  34:             MessageBox.Show(
  35:                 string.Format("myData.Name value is {0}.", name),
  36:                 "System Information",
  37:                 MessageBoxButton.OK,
  38:                 MessageBoxImage.Information);
  39:         }
  40:         #endregion
  41:  
  42:         #region OneWay绑定
  43:         private void btnOneWayeBindingChange_Click(object sender, RoutedEventArgs e)
  44:         { 
  45:             MyData source = (MyData)(panelOneWay.DataContext);
  46:             source.Name = "Jerry";
  47:  
  48:             MessageBox.Show(
  49:                 "myData.Name has been changed to Jerry",
  50:                 "System Information",
  51:                 MessageBoxButton.OK,
  52:                 MessageBoxImage.Information);
  53:         }
  54:  
  55:         private void btnOneWayBindingGet_Click(object sender, RoutedEventArgs e)
  56:         { 
  57:             MyData source = (MyData)(panelOneWay.DataContext);
  58:  
  59:             string name = source.Name;
  60:  
  61:             MessageBox.Show(
  62:                 string.Format("myData.Name value is {0}.", name),
  63:                 "System Information",
  64:                 MessageBoxButton.OK,
  65:                 MessageBoxImage.Information);
  66:         }
  67:         #endregion
  68:  
  69:         #region TwoWay绑定
  70:         private void btnTwoWayBindingChange_Click(object sender, RoutedEventArgs e)
  71:         { 
  72:             MyData source = (MyData)(panelTwoWay.DataContext);
  73:             source.Name = "Jerry";
  74:  
  75:             MessageBox.Show(
  76:                 "myData.Name has been changed to Jerry",
  77:                 "System Information",
  78:                 MessageBoxButton.OK,
  79:                 MessageBoxImage.Information);
  80:         }
  81:  
  82:         private void btnTwoWayBindingGet_Click(object sender, RoutedEventArgs e)
  83:         { 
  84:             MyData source = (MyData)(panelTwoWay.DataContext);
  85:  
  86:             string name = source.Name;
  87:  
  88:             MessageBox.Show(
  89:                 string.Format("myData.Name value is {0}.", name),
  90:                 "System Information",
  91:                 MessageBoxButton.OK,
  92:                 MessageBoxImage.Information);
  93:         }
  94:         #endregion
  95:  
  96:         #region OneWayToSource绑定
  97:         private void btnOneWayToSourceBindingChange_Click(object sender, RoutedEventArgs e)
  98:         { 
  99:             MyData source = (MyData)(panelOneWayToSource.DataContext);
 100:             source.Name = "Jerry";
 101:  
 102:             MessageBox.Show(
 103:                 "myData.Name has been changed to Jerry",
 104:                 "System Information",
 105:                 MessageBoxButton.OK,
 106:                 MessageBoxImage.Information);
 107:         }
 108:  
 109:         private void btnOneWayToSourceBindingGet_Click(object sender, RoutedEventArgs e)
 110:         { 
 111:             MyData source = (MyData)(panelOneWayToSource.DataContext);
 112:  
 113:             string name = source.Name;
 114:  
 115:             MessageBox.Show(
 116:                 string.Format("myData.Name value is {0}.", name),
 117:                 "System Information",
 118:                 MessageBoxButton.OK,
 119:                 MessageBoxImage.Information);
 120:         }
 121:         #endregion
 122:     }
 123: }

程序执行,我们可以得到如下的结论:

  • 对于OneTime绑定:在界面中显示的为数据源的初始值,更改数据源的值的时候,不会更改界面的数据显示;更改界面的数据也不会影响到数据源的数据。
  • 对于OneWay绑定:在界面中显示的数据可以随数据源的值的变化而变化,但更改界面的数据不会影响到数据源。
  • 对于TwoWay绑定:界面中显示的数据及数据源的数据可以双向显示及更新。
  • 对于OneWayToSource绑定:初始时界面的数据为空;更改界面的数据可以影响数据源的值,但是更改数据源的值不会体现在界面上。

转载于:https://www.cnblogs.com/J-FoX/archive/2012/06/07/2539992.html

更多相关:

  • mixamo网站FBX模型带骨骼绑定动作库,unity游戏各职业人物动画,兼容3dmax maya c4d iclone blender等主流3D软件 mixamo游戏3D模型带骨骼绑定FBX动作库 大小解压后:17.2G 素材获取:mixamo网站FBX模型带骨骼绑定动作库-云桥网  ...

  • Angular4.0基础知识之组件Angular4.0基础知识之路由Angular4.0依赖注入Angular4.0数据绑定&管道 数据绑定 数据绑定允许你将组件控制器的属性和方法与组件的模板连接起来,大大降低了开发时的编码量。 常见的表现形式有: 插值表达式:

    {{title}}

    ,即把属性|表达式插入到HTML标签中...

  • 引言 在这个-SLAM建图和导航仿真实例-项目中,主要分为三个部分,分别是 (一)模型构建(二)根据已知地图进行定位和导航(三)使用RTAB-MAP进行建图和导航 该项目的slam_bot已经上传我的Github。 这是第三部分,完成效果如下 图1 建图和导航 三、使用RTAB-Map进行建图和导航 1. rtab...

  • 引言 在这个-SLAM建图和导航仿真实例-项目中,主要分为三个部分,分别是 (一)模型构建(二)根据已知地图进行定位和导航(三)使用RTAB-MAP进行建图和导航 该项目的slam_bot已经上传我的Github。 由于之前的虚拟机性能限制,我在这个项目中使用了新的ubantu 16.04环境,虚拟机配置 内存 8GCPU...

  • [{name:1},{name:2}].forEach((v,i,ar) => {console.log(v,i,ar)});//基础遍历[{name:1},{name:2}].map((v) => v.name);//[1,2]返回对象数组中指定字段值的一位数组(不改变原始数组)[{name:1},{name:2},{name:3}...

  • 体验内容 使用gmapping方法利用turtlebot底盘移动信息和激光雷达数据进行建图。 1. 安装一些依赖包 sudo apt-get install ros-melodic-move-base* sudo apt-get install ros-melodic-map-server* sudo apt-get insta...

  • 前言 我们知道Java/Python这种语言能够很好得 支持反射。反射机制 就是一种用户输入的字符串到对应实现方法的映射,比如http接口中 用户传入了url,我们需要调用该url对应的方法/函数对象 从而做出对应的操作。 而C++ 并没有友好得支持这样的操作,而最近工作中需要通过C++实现http接口,这个过程想要代码实现得优雅...

  • 文档树Document Object Model (DOM) 为文档对象模型, 它使用对象的表示方式来表示对应的文档结构及其中的内容。下面为一个样例 p 元素在文档中的对象所包含的所有属性。控制台:p#domaccessKey: ""align: ""assignedSlot: nullattributeStyleMap: Style...

  • 1、封装 什么是封装?   1.对外部隐藏内部的属性,以及实现细节,给外部提供使用的接口     注意:封装有隐藏的意思,但不是单纯的隐藏     学习封装的目的:就是为了能够限制外界对内部数据的访问   python中属性的权限分为两种:   1.公开的     没有任何限制,谁都可以访问   2.私有的     只有当前类本身能狗...

  • jquery:js框架; 主要区别在dom的操作 jq需要引入文件并且引入顺序在最上面; 找元素 操作元素 js:doucument.getElementById..classname,tagname,name jq:$(选择器) dom是js对象 jqDom是jquery对象 操作内容 js:dom.innerHTML(非表单元素)...

  • Mock.js 的语法规范包括两部分: 数据模板定义规范(Data Template Definition,DTD)数据占位符定义规范(Data Placeholder Definition,DPD)1.数据模板定义规范 DTD 数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值: // 属性名 name // 生...

  • vue   vue.js 是用于构建交互式的 Web 界面的库。它提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。从技术上讲, Vue.js 集中在 MVVM 模式上的视图模型层,并通过双向数据绑定连接视图和模型。实际的 DOM 操作和输出格式被抽象出来成指令和过滤器。相比其它的 MVVM 框架,Vue.j...