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相关推荐

  1. WPF入门第四篇 WPF模板

    WPF模板 1.ControlTemplate 上一篇已经试用过控件模板,我们知道WPF的控件都是继承自Control,在Control类中有一个Template属性,类型就是ControlTempl ...

  2. wpf入门第七篇 使用Squirrel自动更新应用

    前言 本文是wpf入门系列第7篇,面向有winform或者web前端基础的.并且也有C#基础的同学. 本文简单的介绍了如何使用 Squirrel 来为 WPF 客户端 进行自动检查更新. Squirr ...

  3. WPF入门第三篇 ControlTemplate、Trigger与Storyboard

    ControlTemplate.Trigger与Storyboard ControlTemplate通常用在Style中,Trigger通常作为ControlTemplate的一部分,StoryBoa ...

  4. Avalonia跨平台入门第六篇之Grid动态分割

    前面玩耍了ListBox多选,今天在他的基础上对Grid进行动态分割;这个效果其实在Xamarin中已经实现过了;其实都没太大区别;直接看效果吧: 在ListBox中选择了具体的布局后进行Grid布局 ...

  5. Android JNI入门第六篇——C调用Java

    本篇将介绍在JNI编程中C调用Java实现. ×××地址:http://download.csdn.net/detail/xyz_lmn/4868265 关键代码: java: public clas ...

  6. java script 6 折线_Java入门第六篇:Java script(js)的事件

    [js中的事件分类] 1.鼠标事件 onclick.ondbclick.onmouseover.onmouseout 等 2.HTML事件: onload/onunload/onsubmit/onre ...

  7. Android JNI入门第六篇——基本数据类型使用

    转载请标明出处: http://blog.csdn.net/michael1112/article/details/56672288 江东橘子的博客 前面讲到了Java和native数据类型,这里就开 ...

  8. Android入门第七篇之ListView (二)

    Android入门第六篇之ListView (一) ,讲的是如何制作一个具有两行文本的 自定义控件 ,作为ListView的Item的使用方法.这篇接下来也是围绕ListView和Item,更加深入地 ...

  9. java邮件接收代码,JavaMail入门第四篇 接收邮件(示例代码)

    上一篇JavaMail入门第三篇 发送邮件中,我们学会了如何用JavaMail API提供的Transport类发送邮件,同样,JavaMail API中也提供了一些专门的类来对邮件的接收进行相关的操 ...

最新文章

  1. MVC – 9.mvc整体请求流程
  2. 方立勋_30天掌握JavaWeb_国际化开发
  3. Matlab插值方法大全
  4. 什么是隐形门? 隐形门安装要注意什么
  5. 可对Python运行原理进行可视化分析的工具
  6. 腾讯云总裁邱跃鹏:新基建最大的改变是从硬件到软件的转变
  7. python学习之dict的items(),values(),keys()
  8. CentOS下安装JDK完整步骤
  9. 线性代数导论20——克莱姆法则、逆矩阵、体积
  10. 启动U盘更换背景图片和图标的方法
  11. uni-app:如何运行到微信小程序模拟器需要进行的配置项(一)
  12. 【剑拔峨眉 团队裂变】蜜拓蜜教育高端特训营第二期即将上线
  13. JRE解压缩后手动配置注册表
  14. 刨根问底!!到底什么是文件?什么是流
  15. python数据对比校验_Python对比数据库两张表是否一致
  16. mac游戏排行榜,mac好玩的游戏推荐 (一)
  17. 安装nginx和zookeeper
  18. 一种简单的抽签/抽奖算法逻辑
  19. c++基本输入输出 输出不同精度的PI(程序给出的PI值为 3.14159265358979323846)。
  20. Python学习,类空间问题及类之间的关系

热门文章

  1. 足球大数据分析大小球胜平负的技巧与实例附分析软件
  2. 图像、图形、图片文件格式
  3. OLAP与OLTP的区别
  4. 北京市专精特新中小企业认定要求及流程,补贴60万
  5. JavaBean 技术与 JSP 开发模型练习题
  6. 电脑使用技巧(office 套件英文版切换为中文)
  7. 网络基础知识 第一章上
  8. SATA SSD需要NCQ开启吗?
  9. 八拜之交是指哪八拜?
  10. 用vue实现动态组织结构图