WPF之绑定验证(错误模板使用)

1,前言:

         默认情况下,WPF XAML 中使用的绑定并未开启绑定验证,这样导致用户在UI上对绑定的属性进行赋值时即使因不符合规范内部已抛出异常(此情况仅限WPF中的数据绑定操作),也被程序默认忽略,UI层面也无异常提示,无法确定值是否已更改。而这些问题可通过Validation提供的附加属性,附加事件,错误模板进行检测提示,从而有效的解决绑定中产生的异常问题。

例如以下情况:

<TextBox><TextBox.Text><Binding Path="UnitCost"  >                                                       </Binding></TextBox.Text></TextBox>
public decimal UnitCost{get { return unitCost; }set{//测试UI属性绑定异常抛出捕捉if (value < 0){throw new ArgumentException("值不能小于0");}unitCost = value;OnPropertyChanged(nameof(UnitCost));}}

        在UI层面用户通过绑定将当前的 UnitCost 值设置为小于0时(仅限通过绑定输入的值),虽在代码中已产生异常,但运行程序对该绑定中产生的异常默认进行了忽略,不提示异常,导致该值是否已更新,无法确定。

2,数据验证的应用。

         数据绑定进行数据源更新时先进行验证再进行装换,所以对于文本框而言,数据在验证时都是字符串型。

2.1,开启绑定中的验证通知:NotifyOnValidationError="True"

<TextBox  Grid.Row="2" Grid.Column="1"><TextBox.Text><Binding Path="UnitCost" NotifyOnValidationError="True" ValidatesOnExceptions="True"  ></Binding></TextBox.Text></TextBox>

2.2,开启异常验证捕捉规则:ValidatesOnExceptions="True",用于捕捉在该绑定中产生的任何异常(可选)。

        此设定与以下绑定  ExceptionValidationRule 异常验证规则等同 :

<TextBox  Grid.Row="2" Grid.Column="1"><TextBox.Text><Binding Path="UnitCost" NotifyOnValidationError="True"  ><Binding.ValidationRules><ExceptionValidationRule></ExceptionValidationRule></Binding.ValidationRules></Binding></TextBox.Text></TextBox>

2.3,绑定自定义验证规则。

        自定义的验证规则类需要继承自System.Windows.Controls下的抽象类ValidationRule。

 class RangeValidationRule : ValidationRule{/// <summary>/// 范围上限/// </summary>public decimal MaxNum { get; set; } = 10000;/// <summary>/// 范围下限/// </summary>public decimal MinNum { get; set; }public override ValidationResult Validate(object value, CultureInfo cultureInfo){string valStr = value.ToString();if (string.IsNullOrEmpty(valStr)){return new ValidationResult(false, "不能为空值");}decimal val;if(!decimal.TryParse(valStr,NumberStyles.Any,cultureInfo,out val)){return new ValidationResult(false, "输入的内容非法,请输入有效的货币值");}if(val>MaxNum || val < MinNum){return new ValidationResult(false, $"只能是:{MinNum} - {MaxNum}之间的货币值");}return new ValidationResult(true, "");}}

2.4,在绑定中添加自定义的验证规则,并设置相应属性。

 <TextBox  Grid.Row="2" Grid.Column="1"><TextBox.Text><Binding Path="UnitCost" NotifyOnValidationError="True" ValidatesOnExceptions="True"  ><Binding.ValidationRules><local:RangeValidationRule MinNum="10" MaxNum="10000"></local:RangeValidationRule></Binding.ValidationRules></Binding></TextBox.Text></TextBox>

2.5,验证失败时WPF自动将控件使用的模板切换为由Validation.ErrorTemplate附加属性定义的模板。在文本框中新模板将文本框的轮过改成一条细的红色边框(默认错误模板)。

3,使用Validation提供的附加属性,附加事件对异常进行处理。

Validation.HasError附加属性,验证当前元素是否存在验证错误
Validation.Error附加事件,当前元素验证错误事件(路由事件)
Validation.Errors附加属性,当前元素产生的验证错误信息集合
Validation.ErrorTemplate附加属性,当前的元素的错误模板(模板类型:ControlTemplate)

        Validation.ErrorEvent为附加事件即为路由事件,所以可在其父容器进行注册监听。

3.1,在父容器添加附加事件,监听子元素产生的验证错误。

Validation.Error="Grid_Error"

        示例:

 <Grid Margin="10" DataContext="{Binding ElementName=listBox01, Path=SelectedItem}" Validation.Error="Grid_Error"><Grid.RowDefinitions><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition><RowDefinition ></RowDefinition><RowDefinition Height="3*"></RowDefinition></Grid.RowDefinitions><Grid.ColumnDefinitions><ColumnDefinition Width="auto"></ColumnDefinition><ColumnDefinition ></ColumnDefinition></Grid.ColumnDefinitions><TextBlock Text="Model Number"></TextBlock><TextBox Grid.Column="1" Text="{Binding ModelNumber, TargetNullValue=[Empty]}"></TextBox><TextBlock Grid.Row="1" Text="Model Name"></TextBlock><TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ModelName, TargetNullValue=[Empty]}"></TextBox><TextBlock Grid.Row="2" Text="Unit Cost"></TextBlock><TextBox  Grid.Row="2" Grid.Column="1"><TextBox.Text><Binding Path="UnitCost" NotifyOnValidationError="True" ValidatesOnExceptions="True"  ><Binding.ValidationRules><local:RangeValidationRule MinNum="10" MaxNum="10000"></local:RangeValidationRule></Binding.ValidationRules></Binding></TextBox.Text></TextBox><TextBlock Grid.Row="3" Text="Descriptionz:"></TextBlock><TextBox  Grid.Row="4" Grid.ColumnSpan="2" Style="{x:Null}" Text="{Binding Description}"></TextBox></Grid></Border></Grid>
  private void Grid_Error(object sender, ValidationErrorEventArgs e){if (e.Action == ValidationErrorEventAction.Added){StringBuilder sb = new StringBuilder();sb.AppendLine($"RoutedEvent:{e.RoutedEvent.Name}");sb.AppendLine($"Source:{e.Source}");sb.AppendLine($"ErrorContent:{e.Error.ErrorContent}");sb.AppendLine($"{e.Error.RuleInError.GetType().Name}");//sb.AppendLine($"Message:{e.Error.Exception.Message}");MessageBox.Show(sb.ToString());}}

3.2,根据当前元素的是否出现验证错误进行样式设置。

<Trigger Property="Validation.HasError" Value="true">

        示例:

<Trigger Property="Validation.HasError" Value="true">                               <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" >                                  </Setter></Trigger>

3.3,绑定当前元素的当前验证错误信息。

Path=(Validation.Errors)[0].ErrorContent

        示例:

 <Style.Triggers><Trigger Property="Validation.HasError" Value="true"><Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" ></Setter></Trigger></Style.Triggers>

        注意此时的附加属性样式与Path关联的附加属性样式有差异:

        Property中附加属性无括号包裹:

<Trigger Property="Validation.HasError" Value="true">

        Path中的附加属性需用括号包裹

<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" >

4,错误模板应用。

        当验证控件的Validation.HasError属性被设置为true时,WPF自动将控件使用的模板切换为由Validation.ErrorTemplate附加属性定义的模板。在文本框中新模板将文本框的轮过改成一条细的红色边框。

        ErrorTemplate的类型为ControlTemplate。

4.1,自定义错误模板。

 <Style TargetType="TextBox"><Setter Property="Margin" Value="0,3"></Setter><Setter Property="VerticalContentAlignment" Value="Center"></Setter><Setter Property="Validation.ErrorTemplate"><Setter.Value><ControlTemplate><Border BorderBrush="Green" BorderThickness="1"><DockPanel LastChildFill="True"><TextBlock  DockPanel.Dock="Right" Background="Red" ToolTip="{Binding ElementName=adornedElement1, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" HorizontalAlignment="Center">*</TextBlock><AdornedElementPlaceholder x:Name="adornedElement1"></AdornedElementPlaceholder></DockPanel></Border></ControlTemplate></Setter.Value></Setter></Style>

        错误模板是使用装饰层,装饰层位于普通窗口之上的绘图层。

<AdornedElementPlaceholder x:Name="adornedElement1"></AdornedElementPlaceholder>

        AdornedElementPlaceholder,这里指代被修饰的元素即文本框(AdornedElementPlaceholder必须位于ControlTemplate中,为固定写法。)。

4.2,通过AdornedElementPlaceholder获取被修饰对象上的验证错误信息。

<TextBlock  DockPanel.Dock="Right" Background="Red" ToolTip="{Binding ElementName=adornedElement1, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" HorizontalAlignment="Center">*</TextBlock>

5,效果

6,Demo链接:

https://download.csdn.net/download/lingxiao16888/89263053

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

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

相关文章

《苍穹外卖》前端课程知识点记录

一、VUE基础知识 基于脚手架创建前端工程 1. 环境要求 安装node.js&#xff1a;Node.js安装与配置&#xff08;详细步骤&#xff09;_nodejs安装及环境配置-CSDN博客查看node和npm的版本号 安装Vue CLI&#xff1a;Vue.js安装与创建默认项目&#xff08;详细步骤&#xff09;…

分享一篇关于AGI的短文:苦涩的教训

学习强化学习之父、加拿大计算机科学家理查德萨顿&#xff08; Richard S. Sutton &#xff09;2019年的经典文章《The Bitter Lesson&#xff08;苦涩的教训&#xff09;》。 文章指出&#xff0c;过去70年来AI研究走过的最大弯路&#xff0c;就是过于重视人类既有经验和知识&…

探究Android的多分辨率支持以及各种类型图标尺寸大小

术语和概念 屏幕尺寸 屏幕的物理尺寸&#xff0c;以屏幕的对角线长度作为依据&#xff08;比如 2.8寸&#xff0c; 3.5寸&#xff09;。 简而言之&#xff0c; Android把所有的屏幕尺寸简化为三大类&#xff1a;大&#xff0c;正常&#xff0c;和小。 程序可以针对这三种尺寸…

Docker部署nginx并且实现https访问

实验环境&#xff1a; 在已有的docker环境和nginx镜像的基础上进行操作 1、生成私钥 &#xff08;1&#xff09;openssl genrsa -out key.pem 2048 生成证书签名请求 (CSR) 并自签证书: &#xff08;2&#xff09;openssl req -new -x509 -key key.pem -out cert.pem -day…

DDD:根据maven的脚手架archetype生成ddd多模块项目目录结构

随着领域驱动的兴起&#xff0c;很多人都想学习如何进行ddd的项目开发&#xff0c;那ddd的项目结构是怎么样的&#xff1f;又是如何结合SpringBoot呢&#xff1f;那么针对这个问题&#xff0c;笔者使用maven的archetype封装一个相对通用的ddd的项目目录&#xff0c;方便一键生成…

karpathy Let‘s build GPT

1 introduction 按照karpathy的教程&#xff0c;一步步的完成transformer的构建&#xff0c;并在这个过程中&#xff0c;加深对transformer设计的理解。 karpathy推荐在进行网络设计的过程中&#xff0c;同时利用jupyter notebook进行快速测试和python进行主要的网络的构建。 …

STM32标准库SPI通信协议与W25Q64

目录 一、SPI通信 1.SPI通信简介 2.硬件电路 3.移位示意图 4.SPI基本时序图 &#xff08;1&#xff09;起始和终止 &#xff08;2&#xff09;交换一个字节 模式0&#xff1a; 模式1&#xff1a;​编辑 模式2&#xff1a;​编辑 模式3&#xff1a;​编辑 5.SPI时序 …

初识C语言——第九天

ASCII定义 在 C 语言中&#xff0c;每个字符都对应一个 ASCII 码。ASCII 码是一个字符集&#xff0c;它定义了许多常用的字符对应的数字编码。这些编码可以表示为整数&#xff0c;也可以表示为字符类型。在 C 语言中&#xff0c;字符类型被定义为一个整数类型&#xff0c;它占…

数据仓库实验三:分类规则挖掘实验

目录 一、实验目的二、实验内容和要求三、实验步骤1、创建数据库和表2、决策树分类规则挖掘&#xff08;1&#xff09;新建一个 Analysis Services 项目 jueceshu&#xff08;2&#xff09;建立数据源视图&#xff08;3&#xff09;建立挖掘结构 DST.dmm&#xff08;4&#xff…

43 单例模式

目录 1.什么是单例模式 2.什么是设计模式 3.特点 4.饿汉和懒汉 5.峨汉实现单例 6.懒汉实现单例 7.懒汉实现单例&#xff08;线程安全&#xff09; 8.STL容器是否线程安全 9.智能指针是否线程安全 10.其他常见的锁 11.读者写者问题 1. 什么是单例模式 单例模式是一种经典的&a…

线性数据结构-手写队列-哈希(散列)Hash

什么是hash散列&#xff1f; 哈希表的存在是为了解决能通过O(1)时间复杂度直接索引到指定元素。这是什么意思呢&#xff1f;通过我们使用数组存放元素&#xff0c;都是按照顺序存放的&#xff0c;当需要获取某个元素的时候&#xff0c;则需要对数组进行遍历&#xff0c;获取到指…

【skill】onedrive的烦人问题

Onedrive的迷惑行为 安装Onedrive&#xff0c;如果勾选了同步&#xff0c;会默认把当前用户的数个文件夹&#xff08;桌面、文档、图片、下载 等等&#xff09;移动到安装时提示的那个文件夹 查看其中的一个文件的路径&#xff1a; 这样一整&#xff0c;原来的文件收到严重影…

吴恩达2022机器学习专项课程C2(高级学习算法)W1(神经网络):2.1神经元与大脑

目录 神经网络1.初始动机*2.发展历史3.深度学习*4.应用历程 生物神经元1.基本功能2.神经元的互动方式3.信号传递与思维形成4.神经网络的形成 生物神经元简化1.生物神经元的结构2.信号传递过程3.生物学术语与人工神经网络 人工神经元*1.模型简化2.人工神经网络的构建3.计算和输入…

Java与Go: 生产者消费者模型

什么是生产者消费者模型 生产者-消费者模型&#xff08;也称为生产者-消费者问题&#xff09;是一种常见的并发编程模型&#xff0c;用于处理多线程或多进程之间的协同工作。该模型涉及两个主要角色&#xff1a;生产者和消费者&#xff0c;一个次要角色&#xff1a;缓冲区。 生…

18 内核开发-内核重点数据结构学习

课程简介&#xff1a; Linux内核开发入门是一门旨在帮助学习者从最基本的知识开始学习Linux内核开发的入门课程。该课程旨在为对Linux内核开发感兴趣的初学者提供一个扎实的基础&#xff0c;让他们能够理解和参与到Linux内核的开发过程中。 课程特点&#xff1a; 1. 入门级别&…

办公数据分析利器:Excel与Power Query透视功能

数据分析利器&#xff1a;Excel与Power Query透视功能 Excel透视表和Power Query透视功能是强大的数据分析工具&#xff0c;它们使用户能够从大量数据中提取有意义的信息和趋势&#xff0c;可用于汇总、分析和可视化大量数据。 本文通过示例演示Power Query透视功能的一个小技…

Linux专栏08:Linux基本指令之压缩解压缩指令

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Linux专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Linux基本指令之压缩解压缩指令 编号&#xff1a;08 文章目录 Linu…

Spring Boot与OpenCV:融合机器学习的智能图像与视频处理平台

&#x1f9d1; 作者简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

【模板】二维前缀和

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 二维前缀和板题。 二维前缀和&#xff1a;pre[i][j]a[i][j]pre[i-1][j]pre[i][j-1]-pre[i-1][j-1]; 子矩阵 左上角为(x1,y1) 右下角(x2,y2…

PG控制文件的管理与重建

一.控制文件位置与大小 逻辑位置&#xff1a;pgpobal 表空间中 物理位置&#xff1a;$PGDATA/global/pg_control --pg_global表空间的物理位置就在$PGDATA/global文件夹下 物理大小&#xff1a;8K 二.存放的内容 1.数据库初始化的时候生成的永久化参数&#xff0c;无法更改…