WPF入门第六篇 WPF的Binding
WPF的Binding
在传统的Windows软件中,大部分都是UI驱动程序的模式,也可以说事件驱动程序。WPF作为Winform的升级,它把UI驱动程序彻底改变了,核心回到了数据驱动程序的模式上面,这样,程序就回到了算法和数据。数据,才是真正需要重点处理的。
Binding最为重要的一个特点是通讯,连接着前台与后台。首先看一下Binding最简单的使用方法:
一、元素之间的绑定
这里有3个控件,Slider、TextBox、Label,其中TextBox和Label都作为目标,Slider都作为数据源,把Slider中的值交由两个控件体现,移动滑块,TextBox会自动显示Value的值,也就是FontSize的值。因为两个绑定都设置了双向绑定,所以可以在文本框中输入值,然后丢失焦点,也能反馈回去。
看一下XAML中的绑定语句,这里用的ElementName就是制定要绑定的对象的名字,Path就是要绑定的依赖项属性,Mode就是绑定方式,这里需要说明的是Mode有五种方式:
ⅰ. OneWay 单向绑定
ⅱ. TwoWay 双向绑定
ⅲ. OneTime,最初根据源属性值设置目标属性,以后就忽略所有改变,就是说,只进行初始化。
ⅳ. OneWayToSource,这和OneWay相反。
ⅴ. Default,这是默认形式,它根据目标属性自动设置。
如果把TextBox中的值修改成其他的,滑条位置没有改变,字体大小也没有改变,这是怎么回事呢?当TextBox失去焦点的时候,就会发生相应的改变了。这是因为这个绑定中的默认更新机制,更新机制Binding.UpdateSourceTrigger,这个属性有4个枚举值:
ⅰ. PropertyChange,当值改变的时候,就更新。
ⅱ. LostFocus,当失去焦点的时候更新。
ⅲ. Explicit,当调用BindingExpression.UpdateSource()方法的时候更新,其他情况不会更新。
ⅳ. Default,默认形式。
注意:以上四种更新机制的设定,只会影响源数据,而不会影响目标数据。
二、元素自身的绑定
除了可以绑定别的元素,也可以绑定自身的其他属性,例如Slider自身的Opacity属性和自身的Value属性绑定,当滑块向左移动的时候,会逐渐隐藏起来。
三、后台数据与元素之间的绑定
前面说了元素之间的绑定和元素自身的绑定,最后重点来了,后台数据和前台元素的绑定,这种绑定方式很好地体现了数据驱动程序的运行模式。
首先新建Person类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace WpfHouTaiBindingQianTai
{public class Person{/// <summary>/// 姓名/// </summary>public string Name { get; set; }/// <summary>/// 年龄/// </summary>public int Age { get; set; }}
}
页面后台代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 WpfHouTaiBindingQianTai
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();Person person = new Person { Name = "SoftEasy" };Binding binding = new Binding() { Path = new PropertyPath("Name"), Source = person };this.TxtName.SetBinding(TextBox.TextProperty, binding);}}
}
<Window x:Class="WpfHouTaiBindingQianTai.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfHouTaiBindingQianTai"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><TextBox x:Name="TxtName" HorizontalAlignment="Left" Margin="24,69,0,0"TextWrapping="Wrap" VerticalAlignment="Top" Height="60" Width="600"/></Grid>
</Window>
显示效果:
数据绑定的方式已经写完了。Binding是一条高速公路,那么为了提高数据传递的合法性和有效性,我们要在这条高速公路中建立起一系列的关卡,有的用来转换数据,有的用来校验数据,下面说一下Binding对数据的校验和转换。
(一)Binding的数据校验
Binding的数据校验工作是派生自ValidationRule类,并且对Validate方法进行重写的自定义类!
看一下实例:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;namespace WpfHouTaiBindingQianTai
{public class DataValidationRule : ValidationRule{public override ValidationResult Validate(object value, CultureInfo cultureInfo){double d = 0;if (double.TryParse(value.ToString(),out d)){if(d >= 0 && d<= 100){return new ValidationResult(true, null);}}return new ValidationResult(false, "验证失败!");}}
}
先设计一个校验类,它继承ValidationRule类并且重写Validate方法。使用这个类的时候是创建Binding的时候设置校验的。
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 WpfHouTaiBindingQianTai
{/// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();//Person person = new Person { Name = "SoftEasy" };//Binding binding = new Binding() { Path = new PropertyPath("Name"), Source = person };//this.TxtName.SetBinding(TextBox.TextProperty, binding);Binding binding = new Binding("Value") { Source = this.slider };binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;DataValidationRule dataValidationRule = new DataValidationRule();dataValidationRule.ValidatesOnTargetUpdated = true;binding.ValidationRules.Add(dataValidationRule);binding.NotifyOnValidationError = true;this.TxtFontSize.SetBinding(TextBox.TextProperty, binding);this.TxtFontSize.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));}/// <summary>/// 验证错误/// </summary>/// <param name="sender"></param>/// <param name="e"></param>void ValidationError(object sender,RoutedEventArgs e){if(Validation.GetErrors(this.TxtFontSize).Count > 0){this.TxtFontSize.ToolTip = Validation.GetErrors(this.TxtFontSize)[0].ErrorContent.ToString();}}}
}
<Window x:Class="WpfHouTaiBindingQianTai.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfHouTaiBindingQianTai"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Grid><Label x:Name="LblFontSize" Content="SoftEasy" FontSize="{Binding ElementName=slider ,Path=Value,Mode=TwoWay}" HorizontalAlignment="Left" Margin="24,18,0,0" VerticalAlignment="Top"/><Slider x:Name="slider" HorizontalAlignment="Left" Margin="24,117,0,0"VerticalAlignment="Top" Width="330" Maximum="200" Minimum="20"/> //这里的最大值改成了200,为了测试让它报错<TextBox x:Name="TxtFontSize" HorizontalAlignment="Left" Height="23" Margin="24,69,0,0"TextWrapping="Wrap" Text="{Binding ElementName=slider ,Path=Value ,Mode=TwoWay}"VerticalAlignment="Top" Width="120"/></Grid>
</Window>
显示效果:
因为设置了传过去的值不能是超过0~100,所以当超过了就显示红色边框。在Binding中,默认是会认为数据源是肯定正确的,所以如果将TextBox作为数据源,而Slider作为目标,数据源输入错误是没有显示的,那么怎么解决这个问题呢?设置 dataValidationRule.ValidatesOnTargetUpdated = true;
(二)Binding的数据转换
Binding还有另外一种机制称为数据转换,当Source端指定的Path属性值和Target端指定的目标属性不一致的时候,我们可以添加数据转换器(Convert)。上面我们提到的问题实际上就是double和string类型相互转换的问题,因为处理起来比较简单,所以WPF类库就自己帮我们做了,但有些数据类型转换就不是WPF能帮我们做的了,当遇到这些情况,我们只能自己动手来写Converter,方法是创建一个类并让这个类实现 IValueConverter接口。
//TimeConver.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Data;namespace WpfHouTaiBindingQianTai
{/// <summary>/// 自定义事件转换/// </summary>public class TimeConver : IValueConverter{//当值从绑定源传播给绑定目标时,调用方法Convertpublic object Convert(object value, Type targetType, object parameter, CultureInfo culture){if(value == null){return DependencyProperty.UnsetValue;}DateTime date = (DateTime)value;return date.ToString("yyyy-MM-dd");}//当值从绑定目标传播给绑定源时,调用此方法ConvertBackpublic object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){string str = value as string;DateTime txtDate;if(DateTime.TryParse(str,out txtDate)){return txtDate;}return DependencyProperty.UnsetValue;}}
}
这个就是日期转换类,它有两个方法:
ⅰ. 当值从绑定源传播给绑定目标时,调用方法Convert
ⅱ. 当值从绑定目标传播给绑定源时,调用此方法ConvertBack,方法ConvertBack的实现必须是方法Convert的反向实现。
这两个方法分别在里面写入怎么转换,转换成什么类型就是返回类型。
把这个绑定的Convert属性设置成我们设计的转换类的实例就可以了.
WPF入门第六篇 WPF的Binding相关推荐
- WPF入门第四篇 WPF模板
WPF模板 1.ControlTemplate 上一篇已经试用过控件模板,我们知道WPF的控件都是继承自Control,在Control类中有一个Template属性,类型就是ControlTempl ...
- wpf入门第七篇 使用Squirrel自动更新应用
前言 本文是wpf入门系列第7篇,面向有winform或者web前端基础的.并且也有C#基础的同学. 本文简单的介绍了如何使用 Squirrel 来为 WPF 客户端 进行自动检查更新. Squirr ...
- WPF入门第三篇 ControlTemplate、Trigger与Storyboard
ControlTemplate.Trigger与Storyboard ControlTemplate通常用在Style中,Trigger通常作为ControlTemplate的一部分,StoryBoa ...
- Avalonia跨平台入门第六篇之Grid动态分割
前面玩耍了ListBox多选,今天在他的基础上对Grid进行动态分割;这个效果其实在Xamarin中已经实现过了;其实都没太大区别;直接看效果吧: 在ListBox中选择了具体的布局后进行Grid布局 ...
- Android JNI入门第六篇——C调用Java
本篇将介绍在JNI编程中C调用Java实现. ×××地址:http://download.csdn.net/detail/xyz_lmn/4868265 关键代码: java: public clas ...
- java script 6 折线_Java入门第六篇:Java script(js)的事件
[js中的事件分类] 1.鼠标事件 onclick.ondbclick.onmouseover.onmouseout 等 2.HTML事件: onload/onunload/onsubmit/onre ...
- Android JNI入门第六篇——基本数据类型使用
转载请标明出处: http://blog.csdn.net/michael1112/article/details/56672288 江东橘子的博客 前面讲到了Java和native数据类型,这里就开 ...
- Android入门第七篇之ListView (二)
Android入门第六篇之ListView (一) ,讲的是如何制作一个具有两行文本的 自定义控件 ,作为ListView的Item的使用方法.这篇接下来也是围绕ListView和Item,更加深入地 ...
- java邮件接收代码,JavaMail入门第四篇 接收邮件(示例代码)
上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操 ...
最新文章
- MVC – 9.mvc整体请求流程
- 方立勋_30天掌握JavaWeb_国际化开发
- Matlab插值方法大全
- 什么是隐形门? 隐形门安装要注意什么
- 可对Python运行原理进行可视化分析的工具
- 腾讯云总裁邱跃鹏:新基建最大的改变是从硬件到软件的转变
- python学习之dict的items(),values(),keys()
- CentOS下安装JDK完整步骤
- 线性代数导论20——克莱姆法则、逆矩阵、体积
- 启动U盘更换背景图片和图标的方法
- uni-app:如何运行到微信小程序模拟器需要进行的配置项(一)
- 【剑拔峨眉 团队裂变】蜜拓蜜教育高端特训营第二期即将上线
- JRE解压缩后手动配置注册表
- 刨根问底!!到底什么是文件?什么是流
- python数据对比校验_Python对比数据库两张表是否一致
- mac游戏排行榜,mac好玩的游戏推荐 (一)
- 安装nginx和zookeeper
- 一种简单的抽签/抽奖算法逻辑
- c++基本输入输出 输出不同精度的PI(程序给出的PI值为 3.14159265358979323846)。
- Python学习,类空间问题及类之间的关系