WPF的数据绑定详细介绍
一、WPF数据绑定的概要
数据绑定:是应用程序 UI 与业务逻辑之间建立连接的过程。 如果绑定正确设置并且数据提供正确通知,则当数据的值发生更改时,绑定到数据的视觉元素会自动反映更改。 数据绑定可能还意味着如果视觉元素中数据的外部表现形式发生更改,则基础数据可以自动更新以反映更改。
例如:如果用户编辑 TextBox 元素中的值,则基础数据值会自动更新以反映该更改。
1. 数据绑定涉及到两个方面:
一个是绑定源,一个是绑定目标。绑定源即控件绑定所使用的源数据,绑定目标即数据显示的控件。
2. 对于绑定源,在WPF可以是以下四种:
•CLR对象:可以绑定到CLR类的公开的属性、子属性、索引器上。
•ADO.Net对象:例如DataTable、DataView等 。
•XML文件:使用XPath进行解析 。
•DependencyObject:绑定到其依赖项属性上,即控件绑定控件 。
对于绑定目标,必须是WPF中的DependencyObject,将数据绑定到其依赖项属性上。
二、 绑定的模式
1. 根据数据流的方向,WPF中的数据绑定分为以下四种:
OneWay 绑定:对源属性的更改会自动更新目标属性,但是对目标属性的更改不会传播回源属性。此绑定类型适用于绑定的控件为隐式只读控件的情况。
TwoWay 绑定:对源属性的更改会自动更新目标属性,而对目标属性的更改也会自动更新源属性。此绑定类型适用于可编辑窗体或其他完全交互式 UI 方案 。
OneWayToSource 与 OneWay 相反;它在目标属性更改时更新源属性。
OneTime绑定:该绑定会导致源属性初始化目标属性,但不传播后续更改。
注释:如果无需监视目标属性的更改,则使用 OneWay 绑定模式可避免 TwoWay 绑定模式的系统开销。
大多数属性都默认为 OneWay 绑定,但是一些依赖项属性,通常为用户可编辑的控件的属性,如 TextBox 的 Text 属性和 CheckBox 的 IsChecked 属性,默认为 TwoWay 绑定。
如果要知道依赖项属性绑定在默认情况下是单向还是双向的编程方法可使用 GetMetadata 获取属性的属性元数据,然后检查 BindsTwoWayByDefault 属性的布尔值。
示例代码:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1" HorizontalAlignment="Center">
<Grid Name="GridTable" Height="360" Background="Silver">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Width="130" Height="25" Grid.Row="0" Grid.Column="0" Name="label1">TwoWay</Label>
<TextBox Width="150" Height="25" Grid.Row="0" Grid.Column="1" Name="textBox4" Text="{Binding ElementName=scrollBar1,Path=Value,Mode=TwoWay}" />
<Label Width="130" Height="25" Grid.Row="1" Grid.Column="0" Name="label2">OneWay</Label>
<TextBox Width="150" Height="25" Grid.Row="1" Grid.Column="1" Name="textBox1" Text="{Binding ElementName=scrollBar1, Path=Value,Mode=OneWay}"/>
<Label Width="130" Height="25" Grid.Row="2" Grid.Column="0" Name="label3">OneWayToSource</Label>
<TextBox Width="150" Height="25" Grid.Row="2" Grid.Column="1" Name="textBox2" Text="{Binding ElementName=scrollBar1, Path=Value,Mode=OneWayToSource}" />
<Label Width="130" Height="25" Grid.Row="3" Grid.Column="0" Name="label4">OneTime</Label>
<TextBox Width="150" Height="25" Grid.Row="3" Grid.Column="1" Name="textBox3" Text="{Binding ElementName=scrollBar1, Path=Value,Mode=OneTime}"/>
<ScrollBar Value="30" Minimum="0" Grid.RowSpan="4" Grid.Row="0" Grid.Column="2" Maximum="100" Name="scrollBar1" Width="18" Height="{Binding ElementName=GridTable,Path=Height}" />
</Grid>
</Page>
根据程序执行结果,我们可以得到以下结论:
对于OneWay绑定:在界面中显示的数据可以随数据源的值的变化而变化,但更改界面的数据不会影响到数据源。
对于TwoWay绑定:界面中显示的数据及数据源的数据可以双向显示及更新。
对于OneWayToSource绑定:初始时界面的数据为空;更改界面的数据可以影响数据源的值,但是更改数据源的值不会体现在界面上。
对于OneTime绑定:在界面中显示的为数据源的初始值,更改数据源的值的时候,不会更改界面的数据显示;更改界面的数据也不会影响到数据源的数据。
三、绑定目标值影响绑定源值条件
问题:绑定源的值是在您编辑文本的同时进行更新,还是在您结束编辑文本并将鼠标指针从文本框移走后才进行更新呢?或者在您需要更新的情况下在手动的更新呢?
1. UpdateSourceTrigger 属性是确定触发源更新的原因。
下图中右箭头的点演示 UpdateSourceTrigger 属性的角色:
TwoWay及OneWayToSource是由绑定目标到绑定源方向,若实现绑定目标的值更改影响绑定源的值方式,只需要设置相应控件绑定时的UpdateSourceTrigger的值,其值有三种:
PropertyChanged:当绑定目标属性更改时,立即更新绑定源。
LostFocus:当绑定目标元素失去焦点时,更新绑定源。
Explicit:仅在调用 UpdateSource 方法时更新绑定源。
注释:多数依赖项属性的UpdateSourceTrigger 值的默认值为 PropertyChanged,而 Text 属性的默认值为 LostFocus。
2. 示例
<Page x:Class="WpfDemo.Changed"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Changed">
<Grid Name="GridTable" Height="250" Background="Silver" Width="350">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
<ColumnDefinition Width="100"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Width="90" Height="25" Grid.Column="0" Name="label1" Text="PropertyChanged:"></TextBlock>
<TextBlock Grid.Row="1" Width="90" Height="25" Grid.Column="0" Name="label2" Text="LostFocus:"></TextBlock>
<TextBlock Grid.Row="2" Width="90" Height="25" Grid.Column="0" Name="label3" Text="Explicit:"></TextBlock>
<TextBox Grid.Row="0" Width="150" Height="25" Text="{Binding Path=UserName,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Name="TextBox1" />
<TextBox Grid.Row="1" Width="150" Height="25" Text="{Binding Path=UserName,Mode=TwoWay,UpdateSourceTrigger=LostFocus}" Grid.Column="1" Name="TextBox2" />
<TextBox Grid.Row="2" Width="150" Height="25" Text="{Binding Path=UserName,Mode=TwoWay,UpdateSourceTrigger=Explicit}" Grid.Column="1" Name="txtExplicit" />
<TextBlock Grid.Row="3" Width="90" Height="25" Grid.Column="0" Name="lblResult" Text="结果:"></TextBlock>
<TextBlock Grid.Row="3" Width="90" Height="25" Grid.Column="1" Name="lblDisplay" Text="{Binding Path=UserName,Mode=OneWay}"></TextBlock>
<Button Name="btnChanged" Width="90" Height="25" Grid.Row="3" Grid.Column="2">Explicit</Button>
</Grid>
</Page>
namespace WpfDemo
{
public partial class Changed : Page
{
#region properties
public UserModel CurrentUser
{
get;set;
}
#endregion
#region Constructor
public Changed()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Changed_Loaded);
this.btnChanged.Click += new RoutedEventHandler(btnChanged_Click);
}
#endregion
#region Changed_Loaded
void Changed_Loaded(object sender, RoutedEventArgs e)
{
this.CurrentUser = new UserModel() {UserName="swd"};
this.DataContext = this.CurrentUser;
}
#endregion
#region btnLogon_Click
void btnChanged_Click(object sender, RoutedEventArgs e)
{
this.txtExplicit.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
#endregion
}
public class UserModel
{
public string UserName
{
get;set;}
}
}
程序执行结果如上所述。
四、 数据提供程序
1. XmlDataProvider:
XmlDataProvider访问 XML 数据的方式有以下三种:
可以使用 XmlDataProvider 类嵌入内联 XML 数据。
可以将 Source 属性设置为 XML 数据文件的 Uri。
可以将 Document 属性设置为 XmlDocument。
注释:当 XmlDocument.NodeChanged 事件发生时,XmlDataProvider 执行所有绑定的完全刷新。 特定节点不进行优化。
默认情况下,XmlDataProvider.IsAsynchronous 属性设置为 true,表示默认情况下 XmlDataProvider 检索数据并异步生成 XML 节点的集合。
以下将介绍使用上面所述的三种方式显示xml数据:
示例
<Page x:Class="WpfDemo.xmlBinding"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="xmlBinding" xmlns:local="clr-namespace:WpfDemo">
<Page.Resources>
<XmlDataProvider x:Key="XmlFile" Source="Students.xml" XPath="/Students"></XmlDataProvider>
<XmlDataProvider x:Key="InnerXmlStu" XPath="/Students">
<x:XData>
<Students xmlns="">
<Student><name>swd</name></Student>
<Student><name>awd</name></Student>
<Student><name>asd</name></Student>
</Students>
</x:XData>
</XmlDataProvider>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Height="25" Width="100" Text="引用XML文件"></TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0" Height="25" Width="100" Text="内嵌XML"></TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0" Height="25" Width="100" Text="动态XML"></TextBlock>
<ListBox Name="lisbXmlFile" Grid.Row="0" Grid.Column="1" Height="100" Width="150" ItemsSource="{Binding Source={StaticResource XmlFile},XPath=Student/name}">
</ListBox>
<ListBox Name="lisbInnerXml" Grid.Row="1" Grid.Column="1" Height="100" Width="150" ItemsSource="{Binding Source={StaticResource InnerXmlStu},XPath=Student/name}">
</ListBox>
<ListBox Name="lisbXmlDoc" Grid.Row="2" Grid.Column="1" Height="100" Width="150" ItemsSource="{Binding XPath=Student/name}">
</ListBox>
</Grid>
</Page>
<?xml version="1.0" encoding="utf-8" ?>
<Students>
<Student>
<name>swd</name>
<score>110</score>
</Student>
<Student>
<name>asd</name>
<score>120</score>
</Student>
<Student>
<name>awd</name>
<score>130</score>
</Student>
</Students>
通过以上示例我想大家应该很容易理解与应用。
2. ObjectDataProvider:
ObjectDataProvider 使您能够在 XAML 中创建可用作绑定源的对象,并为您提供以下属性,以对对象执行查询并绑定到结果。
使用 ConstructorParameters 属性将参数传递给对象的构造函数。
使用 MethodName 属性调用一个方法。
使用 MethodParameters 属性将参数传递给该方法。 然后,可以绑定到该方法的结果。
使用ObjectType 指定将提供数据绑定源的对象。
使用 ObjectInstance 属性来指定现有的对象实例作为源
注释:还可以使用 IsAsynchronous 属性指定是在辅助线程还是在活动上下文中执行对象创建。也就是是否异步检索数据。
示例:
C#:
namespace WpfDemo
{
#region CObjectDataProvider
public partial class CObjectDataProvider : Page
{
public CObjectDataProvider()
{InitializeComponent();}
}
#endregion
#region Country
public class Country
{
#region Name
public string Name
{get;set;}
#endregion
#region ProvinceList
public List<Province> ProvinceList
{get;set;}
#endregion
#region GetAllCity
public static List<Country> GetAllCity()
{
return new List<Country>{
new Country
{
Name = "中国",
ProvinceList = new List<Province>
{
new Province{ Name="福建省",
CityList=new List<City>{new City{Name="福州市"},new City{Name="厦门市"},new City{Name="漳州市"},new City{Name="泉州市"}}
},
new Province{Name="江苏省",
CityList=new List<City>{
new City{Name="苏州市"},new City{Name="南京市"},new City{Name="扬州市"},new City{Name="无锡市"}}
},
new Province{Name="江西省",
CityList=new List<City>{new City{Name="南昌市"},new City{Name="九江市"}}}}
}
};
}
#endregion
}
#endregion
#region Province
public class Province
{
#region Name
public string Name
{get;set;}
#endregion
#region CityList
public List<City> CityList
{get;set;}
#endregion
}
#endregion
#region City
public class City
{
#region Name
public string Name
{get;set;}
#endregion
}
#endregion
}
五、类型转换与数据校验
1. IValueConverter接口
提供一种将自定义逻辑应用于绑定的方式。
在Binding时,数据源对象到目标对象之间(或者目标对象到数据源对象)可能需要某种转换。这时只需实现IValueConverter接口自定义值转换器即可。
接口原型定义:
public interface IValueConverter
{
object Convert(object value, Type targetType, object parameter, CultureInfo culture);
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
}
参数value是要转换的值,typeTarget是转换后的值类型,parameter是Binding 类的 ConverterParameter传递过来的参数。
Convert方法:数据绑定引擎在将值从绑定源传播给绑定目标时,调用此方法。
ConvertBack方法:数据绑定引擎在将值从绑定目标传播给绑定源时,调用此方法。
ValueConversion属性作用是告诉自定义转换器类可以转换的源数据和目标数据的 类型(ValueConversion属性将在稍后的示例中看到)。
2. ValidationRule类
提供一种为检查用户输入的有效性而创建自定义规则的方法。
ValidationRule : 所有自定义验证规则的基类。提供了让用户定义验证规则的入口。
ExceptionValidation :表示一个规则,该规则检查在绑定源属性更新过程中引发的异常。它是一个内置的规则,它检查在绑定源属性更新过程中引发的异常。
ValidationResult : 数据验证结果的表现方式。ValidationRule对象的Validate方法执行完毕后通过ValidationResult来表示验证的结果。这里包含了错误信息—ErrorContent,数据是否有效—IsValid。ValidResult 为 ValidationResult 的有效实例。
ValidationError :表示一个验证错误,该错误在 ValidationRule 报告验证错误时由绑定引擎创建。
<Page x:Class="WpfDemo.TypeConvertAndValidationRule"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TypeConvertAndValidationRule"
xmlns:src="clr-namespace:WpfDemo">
<Grid Height="250" Width="360" Background="Silver">
<Grid.RowDefinitions>
<RowDefinition>
</RowDefinition>
<RowDefinition>
</RowDefinition>
<RowDefinition>
</RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition>
</ColumnDefinition>
<ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Height="25" Width="100" Text="生日" Grid.Row="0" Grid.Column="0"></TextBlock>
<TextBox Name="txtBirthday" Height="25" Width="150" Grid.Row="0" Grid.Column="1">
<TextBox.Text>
<Binding Path="Birthday" UpdateSourceTrigger="LostFocus" Mode="TwoWay">
<Binding.ValidationRules><src:ValidationDateTimeRule/></Binding.ValidationRules>
<Binding.Converter><src:MyConverterOfBirthFormat/></Binding.Converter>
</Binding>
</TextBox.Text>
<TextBox.ToolTip>
<Binding RelativeSource="{RelativeSource Self}" Path="(Validation.Errors) [0].ErrorContent"></Binding>
</TextBox.ToolTip> </TextBox>
<TextBlock Height="25" Width="150" Grid.Row="1" Text="{Binding Path=Birthday,Mode=OneWay}" Grid.Column="1"></TextBlock>
<TextBlock Height="25" Width="100" Text="电子邮件格式检查" Grid.Row="2" Grid.Column="0"></TextBlock>
<TextBox Height="25" Width="150" Grid.Row="2" Grid.Column="1">
<TextBox.Text>
<Binding Path="EMail">
<Binding.ValidationRules><ExceptionValidationRule /></Binding.ValidationRules>
</Binding> </TextBox.Text>
<TextBox.ToolTip>
<Binding RelativeSource="{RelativeSource Self}" Path="(Validation.Errors)[0].ErrorContent"></Binding>
</TextBox.ToolTip> </TextBox>
</Grid>
</Page>
namespace WpfDemo
{
#region TypeConvertAndValidationRule
public partial class TypeConvertAndValidationRule : Page
{
public TypeConvertAndValidationRule()
{
InitializeComponent();
this.DataContext = new UserInfo { Name = "swd", Birthday =System.Convert.ToDateTime("1987/10/21"), EMail = "swd@126.com" };
}
}
#endregion
#region UserInfo
public class UserInfo
{
#region Name
public string Name
{get;set;}
#endregion
#region Birthday
public DateTime Birthday
{get;set;}
#endregion
#region EMail
private string email;
public string EMail
{
get
{return email;}
set
{
this.email = value;
Regex r = new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$");
if (!r.IsMatch(value))
{
throw new ApplicationException("电子邮件格式有误!");
}
}
}
#endregion
}
#endregion
六、 绑定集合对象
1. ICollectionView接口
允许集合具有当前记录管理、自定义排序、筛选和分组这些功能。比如排序,分组,筛选,导航以及其它自定义视图,并且这不会影响到你的后台数据的实际存储。
2. ObservableCollection <T> 类
表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。
3. WPF MVVM概要
MVVM(Model-View-ViewModel)是由MVC,MVP演变而来。MVVM分离了逻辑与界面,解放业务逻辑。
WPF的数据绑定详细介绍的更多相关文章
- android之ListView,详细介绍实现步骤,举例,自定义listview适配器
android之ListView,详细介绍实现步骤,举例,自定义listview适配器 本文来源于www.ifyao.com禁止转载!www.ifyao.com android中如何使用listVie ...
- vue对比其他框架详细介绍
vue对比其他框架详细介绍 对比其他框架 — Vue.jshttps://cn.vuejs.org/v2/guide/comparison.html React React 和 Vue 有许多相似之处 ...
- SpringMVC之六:Controller详细介绍
一.简介 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Mo ...
- wpf Content数据绑定StringFormat起作用的原理和解决
原文:wpf Content数据绑定StringFormat起作用的原理和解决 <Window x:Class="WpfOne.Bind.Bind6" xmlns=" ...
- WPF:数据绑定总结(1) https://segmentfault.com/a/1190000012981745
WPF:数据绑定总结(1) visual-studio c# 1.3k 次阅读 · 读完需要 16 分钟 0 一.概念:什么是数据绑定? WPF中的数据绑定:是在应用程序 UI 与业务逻辑之间建立 ...
- [No0000A7]批处理经常用到的变量及批处理>NUL详细介绍
绝对路径是指调用绝对的程序位置的路径,例如: start C:\Windows\test.exe 相对路径是文件改变路径以后还会按照变量的路径所在位置去调用,例如: start %WINDIR%\te ...
- linux配置网卡IP地址命令详细介绍及一些常用网络配置命令
linux配置网卡IP地址命令详细介绍及一些常用网络配置命令2010-- 个评论 收藏 我要投稿 Linux命令行下配置IP地址不像图形界面下那么方 便,完全需要我们手动配置,下面就给大家介绍几种配置 ...
- _MSC_VER详细介绍
_MSC_VER详细介绍 转自:http://www.cnblogs.com/braver/articles/2064817.html _MSC_VER是微软的预编译控制. _MSC_VER可以分解为 ...
- php CGI、Fastcgi、PHP-FPM的详细介绍与之间的关系
以下PHP CGI.Fastcgi.PHP-FPM的一些信息归纳和汇总----->详细介绍与之间的关系 一:CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的 web ...
随机推荐
- hdu 4055 Number String(dp)
Problem Description The signature of a permutation is a string that is computed as follows: for each ...
- 【转】Devexpress使用之:GridControl控件(合并表头)
Devexpress系列控件功能很强大,使用起来也不太容易,我也是边摸索边使用,如果有时间我会把常用控件的使用方法整理出来的. using System; using System.Collectio ...
- 一个提供jsp免费空间的站点
EATJ美国JSP虚拟主机商提供免费jsp空间申请,50M空间,每月3G的流量限制,支持Java5.0/6.0.PHP.CGI.Perl.SSI等,提供2个MySQL数据库,Tomcat v5.5/v ...
- 从free命令看Linux内存管理
free命令是Linux系统下用来查看内存使用情况的,例如: $ free -h total used free shared buffers cached Mem: 7.8G 6.6G 1.3G 0 ...
- 【转】Difference between Point-To-Point and Publish/Subscribe JMS Messaging Models
Difference between Point-To-Point and Publish/Subscribe JMS Messaging Models Point-to-Point (PTP) ...
- 13 java 设计模式--单例模式
/** * 单例 */ public class JobSchedulerService { //防止类外部通过new实例化该类 private JobSchedulerService() { } / ...
- Mysql存储过程分析
为了搞明白为什么mysql的存储过程是高效的,我们需要理解mysql的执行流程是什么,当输入sql语句之后,mysql会先进行sql语句语法正确性检查,然后再进行编译,然后才执行,最后把结果返回.如下 ...
- 数据画图 jpgraph & chart.js
今天想到要研究下“用图表的形式来呈现数据”这个主题.对比了下两种实现的方法: 方法一:通过php代码在服务器端生成图像,再将图像传回客户端.使用jpGraph类库. 方法二:通过js和html5技术, ...
- 浅析Javascript原型继承(转)
引自: http://blog.csdn.net/kittyjie/article/details/4380918 原作者解释的浅显易懂,非常不错的JavaScript prototype总结 JS没 ...
- JavaScript 语法陷阱
没有一门编程语言是完美的,JavaScript 也不例外,它语法陷阱重重,防不胜防: 加号 "with" 分号自动插入 声明提升 "eval" 多行字符串 变量 ...