WPF入门第六篇 WPF的Binding

news2024/11/30 6:40:48

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
    {
        //当值从绑定源传播给绑定目标时,调用方法Convert
        public 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");
        }

        //当值从绑定目标传播给绑定源时,调用此方法ConvertBack
        public 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属性设置成我们设计的转换类的实例就可以了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/87612.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计服装销售商城系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

【ESP8266-NodeMCU软硬串口通讯】

1. 前言 SoftwareSerial库允许在Arduino板的其他数字引脚上进行串行通信,使用软件复制功能(因此得名“SoftwareSerial”)。可以有多个软件串行端口,速度高达115200 bps。参数为需要该协议的设备启用反向信令。 1.1 要使用此库 请执行以下操作: #include <SoftwareS…

Prometheus的PromQL语法讲解和使用示例

目录1. PromQL介绍2. 基本用法2.1 查询时间序列2.2 范围查询2.3 时间位移操作2.4 聚合操作2.5 标量和字符串3. 表达式的合法格式4. PromQL操作符4.1 数学运算4.2 布尔运算4.3 集合运算符4.4 操作符优先级4.5 聚合操作1. PromQL介绍 PromQL提供对时间序列数据进行逻辑运算、过滤…

SpringBoot 配置文件

哈喽呀&#xff0c;你好呀&#xff0c;欢迎呀&#xff0c;快来看一下这篇宝藏博客吧~~~ 1. 配置文件的作用 对于Spring Boot项目而言,所有重要的数据都是在配置文件中配置的,比如: 项目的启动端口;数据库的连接信息(包含用户名和密码的设置);用于发现和定位问题的普通日志和异…

第09讲:路由开发

一、使用脚手架创建vue路由项目 项目的创建步骤参考&#xff1a; 在预设中选择Router 这里输入n&#xff0c;表示不使用history模式 选择In dedicated config files表示将配置分开存放 项目已经创建完成&#xff0c;使用VSCode打开&#xff08;部分win10 以上机型请用管理员…

[GO] 图书管理系统API

图书管理系统 1. 创建项目 2. 配置goproxy GOPROXYhttps://goproxy.cn 3. 添加格式化工具 4. 定义目录结构 |---- Readme.md //项目说明 |---- config // 配置文件(mysql配置,ip,端口,用户名,密码等) |---- controller // CLD服务入口,负责处理路由,参数校验,请求转发 |----…

缓存实现方式

为啥需要缓存&#xff1f; mysql关系型数据库&#xff0c;查询时需要磁盘IO&#xff0c;会消耗系统性能并且耗时&#xff0c;当数据变化量较小&#xff0c;并且响应要快的话&#xff0c;可以考虑使用缓存 服务端缓存方式有哪些&#xff1f; 服务端缓存方式&#xff1a; ①可以使…

git push/pull 超时问题解决

使用代理&#xff0c;发现git仓库浏览器可以访问到&#xff0c;但是本地 push/pull 时提示超时&#xff0c;这里提供一个方案供参考&#xff08;亲测有效&#xff09;&#xff1a; 修改系统的DNS为&#xff1a;114.114.114.114

基于java SSM框架的校园二手交易平台设计

一、项目介绍 游客&#xff1a;浏览商品&#xff0c;登录、注册 用户&#xff1a;浏览商品&#xff0c;发布&#xff0c;评论商品&#xff0c;我的订单&#xff0c;收藏&#xff0c;修改个人信息&#xff0c;搜索&#xff0c;回复评论 管理员&#xff1a;商品分类管理&#xff…

基于MATLAB开发AUTOSAR软件应用层模块-part13.AUTOSAR Dictionary-3 编辑AUTOSAR元素-SWC 和PORTS

配置SWC 此处可以配置SWC的名字和类型,类型包含: Application 应用组件 ComplexDiviceDriver 复杂驱动组件 EcuAbstraction ECU 抽象组件 SensorActuator 传感器执行器组件

学会python可以做哪些兼职?

前言 以我差不多四年的 Python 使用经验来看&#xff0c;大概可以按以下这些路子来赚到钱&#xff0c;但编程技能其实只是当中必不可少的一部分&#xff0c;搭配其它技能栈食用风味更佳。 1、爬虫 很多人入门 Python 的必修课之一一定是 Web 开发和爬虫&#xff0c;但这两项…

如何使用Github+picGo搭建图床???

最开始我使用iPic微博图床匿名上传&#xff0c;但是&#xff01;&#xff01;&#xff01;当我不小心上传了隐私文件后&#xff0c;删除特别麻烦(联系新浪客服,提供图片是自己上传的证据才给予处理)&#xff0c;因为白嫖图床&#xff0c;总担心挂掉&#xff0c;而且不利于备份。…

独立性能环境的重要性

独立性能环境的重要性 有些同学担心&#xff0c;由于性能测试环境和线上环境配置不一致&#xff0c;会导致线下环境得到的性能结果无法发现足够多的性能问题&#xff0c;无法对线上环境的容量评估/稳定性保障带来足够的参考。其中担心的重点有如下几点&#xff1a; 配置不一致&…

47 岁从华为退休,操作系统老兵转战 OpenHarmony 生态 | 近匠

【CSDN 编者按】开源生态建设作为开源发展的关键&#xff0c;在国内仍缺乏足够的多的成功先例&#xff0c;开源操作系统生态到底该如何建设&#xff1f;本期《近匠》邀请到专注于 OpenHarmony 操作系统生态共建的杨启彬与我们分享他的实践经验。 本期受访嘉宾&#xff1a; 杨启…

软件测试工程师面试如何描述自动化测试是怎么实现的?

软件测试工程师面试的时候&#xff0c;但凡简历中有透露一点点自己会自动化测试的技能点的描述&#xff0c;都会被面试官问&#xff0c;那你结合你的测试项目说说自动化测试是怎么实现的&#xff1f;一到这里&#xff0c;很多网友&#xff0c;包括我的学生&#xff0c;也都一脸…

【车载开发系列】UDS诊断---OBD基础概述

【车载开发系列】UDS诊断—OBD基础概述 UDS诊断---OBD基础概述【车载开发系列】UDS诊断---OBD基础概述一.什么是OBD二.OBD和UDS的区别三.OBD应用功能与应用领域四.OBD的特点有哪些五.OBD的服务概述六.OBD服务中的DTC七.OBD服务中0x03和0x07的区别八.Pending DTC有什么用九.OBD的…

昇腾携手OpenMMLab,支持海量算法仓库的昇腾AI推理部署

摘要&#xff1a;近日&#xff0c;昇腾AI联合浦江实验室&#xff0c;正式实现OpenMMLab算法仓库在昇腾的异构计算架构CANN上的推理部署&#xff0c;目前相关代码已推入MMDeploy 0.10.0版本&#xff0c;并在GitHub正式发布。本文分享自华为云社区《昇腾携手OpenMMLab&#xff0c…

标准库 - Object

一、Object 对象&#xff0c;同时也是一个构造函数。 Object 对象提供了很多操作对象的属性和方法&#xff0c;也是对应的原型。 1.Objcet() 作为函数使用 可以把其他数据类型转为一个包装对象 <script> var a Object("a");// 传入字符串就可以包装为字符串…

面试必备:分库分表经典15连问

前言 大家好&#xff0c;我是田螺。我们去面试的时候&#xff0c;几乎都会被问到分库分表。田螺哥整理了分库分表的15道经典分库分表面试题&#xff0c;大家看完肯定会有帮助的。 公众号&#xff1a;捡田螺的小男孩github地址&#xff0c;感谢每颗star&#xff1a;github 1. 我…

Jmeter随机参数各种搭配

目录&#xff1a;导读 前言 一、两个固定值之间随机生成一个值&#xff0c;应用场景没有限制 二、接下来使用CSV文件按提前写好的值作为参数&#xff0c;执行场景需要提前根据实际情况配置好执行次数 三、在固定的多个值中&#xff0c;随机选取一个值作为参数&#xff0c;执…