WPF/C#:BusinessLayerValidation

news2024/11/20 3:25:34

BusinessLayerValidation介绍

BusinessLayerValidation,即业务层验证,是指在软件应用程序的业务逻辑层(Business Layer)中执行的验证过程。业务逻辑层是应用程序架构中的一个关键部分,负责处理与业务规则和逻辑相关的操作。业务层验证的主要目的是确保数据在业务规则和逻辑上的有效性,从而维护数据的完整性和一致性。

  • 业务层验证的主要目的是确保数据在业务规则和逻辑上的有效性。这包括检查数据是否符合特定的业务规则、数据完整性检查、数据一致性检查等。
  • 通过在业务层进行验证,可以确保数据在整个应用程序中的正确性和一致性,而不仅仅是在用户界面层。

在WPF中如何实现BusinessLayerValidation

在WPF Samples中有一个Demo提到了BusinessLayerValidation。

该Demo结构如下所示:

image-20240625143242336

实现的效果如下所示:

当输入值是字符时会提示不是正确的形式,当输入小于0或大于150的数时会有一个自定义的提示。

IDataErrorInfo接口

在WPF中实现业务逻辑层的验证可以使用IDataErrorInfo接口与INotifyDataErrorInfo 接口。这个Demo使用的是IDataErrorInfo接口。IDataErrorInfo接口主要用于在数据绑定场景中提供自定义的验证错误信息。IDataErrorInfo接口包含两个成员:

string IDataErrorInfo.Error { get; }

这个属性返回一个字符串,表示整个对象的错误信息。如果对象没有错误,应该返回一个空字符串或null。

string IDataErrorInfo.this[string columnName] { get; }

这个索引器用于返回指定属性的错误信息。columnName参数表示属性的名称,索引器应该返回该属性的错误信息。如果属性没有错误,应该返回一个空字符串或null。

通过实现IDataErrorInfo接口,可以为数据对象提供详细的验证错误信息,这些信息可以在用户界面中显示,帮助用户理解和纠正输入错误。

定义一个实现该接口的Person类:

 public class Person : IDataErrorInfo
 {
     public int Age { get; set; }
     public string Error => null;

     public string this[string name]
     {
         get
         {
             string result = null;

             if (name == "Age")
             {
                 if (Age < 0 || Age > 150)
                 {
                     result = "Age must not be less than 0 or greater than 150.";
                 }
             }
             return result;
         }
     }
 }

定义资源

  <local:Person x:Key="Data"/>

现在xaml中定义了一个Person对象为资源,键名为Data。

<!--The tool tip for the TextBox to display the validation error message.-->
<Style x:Key="TextBoxInError" TargetType="TextBox">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip"
                    Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                                    Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
    </Style.Triggers>
</Style>

为TextBox控件定义了一个键名为TextBoxInError的样式(Style)。

触发器(Trigger)

在WPF中,触发器(Trigger)是一种用于在特定条件满足时改变控件外观或行为的机制。Trigger通常用于Style

或ControlTemplate中,以便在属性值变化或事件发生时自动应用视觉效果或行为。

WPF 中的Trigger可以分为以下几类:

  • Property Trigger
  • Data Trigger
  • Event Trigger
  • MultiTrigger
  • MultiDataTrigger

Property Trigger是最常用的触发器类型。它根据依赖属性的值来应用视觉效果或行为。

示例:

<Style TargetType="Button">
  <Style.Triggers>
    <Trigger Property="IsMouseOver" Value="True">
      <Setter Property="Background" Value="Yellow"/>
    </Trigger>
  </Style.Triggers>
</Style>

在这个例子中,当鼠标悬停在按钮上时,按钮的背景色会变为黄色。

Data Trigger类似于Property Trigger,但它用于绑定数据上下文中的属性,而不是控件本身的依赖属性。

示例:

<Style TargetType="TextBlock">
  <Style.Triggers>
    <DataTrigger Binding="{Binding Path=IsEnabled}" Value="False">
      <Setter Property="Foreground" Value="Gray"/>
    </DataTrigger>
  </Style.Triggers>
</Style>

在这个例子中,当数据上下文中的IsEnabled属性为False时,文本块的前景色会变为灰色。

Event Trigger用于在特定事件发生时执行动画或命令。

示例:

<Button Content="Click Me">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:1"/>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

在这个例子中,当按钮被点击时,按钮的透明度会从 1 变为 0,持续 1 秒钟。

MultiTriggerMultiDataTrigger允许你指定多个条件,只有当所有条件都满足时,才会应用视觉效果或行为。

示例:

<Style TargetType="TextBox">
  <Style.Triggers>
    <MultiTrigger>
      <MultiTrigger.Conditions>
        <Condition Property="IsFocused" Value="True"/>
        <Condition Property="Text" Value=""/>
      </MultiTrigger.Conditions>
      <Setter Property="BorderBrush" Value="Red"/>
    </MultiTrigger>
  </Style.Triggers>
</Style>

在这个例子中,当文本框获得焦点且文本为空时,文本框的边框颜色会变为红色。

通过使用这些触发器,可以创建动态和响应式的用户界面,根据不同的条件自动调整控件的外观和行为。

通过回顾WPF中的这些触发器,再来看看现在遇到的触发器:

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

这是属性触发器,当Validation.HasError属性的值为true时,会将ToolTip的值设置为(Validation.Errors)[0].ErrorContent的值。

之前我们已经接触过StaticSource这表示是静态资源,现在这里是RelativeSource,让我们来了解一下它吧。

RelativeSource是WPF中的一个绑定标记扩展,用于指定数据绑定的源相对于绑定目标的位置。它允许你在绑定表达式中引用相对于当前控件或数据上下文的另一个对象,而不是直接指定一个固定的源对象。

RelativeSource可以用于以下几种模式:

  • Self:绑定到控件自身的一个属性。
  • TemplatedParent:绑定到应用控件模板的控件。
  • PreviousData:在数据模板中绑定到前一个数据项。
  • FindAncestor:绑定到可视树中的祖先控件。

可以创建更灵活和动态的数据绑定,特别是在处理复杂的用户界面和控件模板时。

再来看文本框部分:

 <StackPanel Margin="20">
     <TextBlock>Enter your age:</TextBlock>
     <TextBox Style="{StaticResource TextBoxInError}">
         <TextBox.Text>
             <!--By setting ValidatesOnExceptions to True, it checks for exceptions
             that are thrown during the update of the source property.
             An alternative syntax is to add <ExceptionValidationRule/> within
             the <Binding.ValidationRules> section.-->
             <Binding Path="Age" Source="{StaticResource Data}"
                      ValidatesOnExceptions="True"
                      UpdateSourceTrigger="PropertyChanged">
                 <Binding.ValidationRules>
                     <!--DataErrorValidationRule checks for validation 
                         errors raised by the IDataErrorInfo object.-->
                     <!--Alternatively, you can set ValidationOnDataErrors="True" on the Binding.-->
                     <DataErrorValidationRule/>
                 </Binding.ValidationRules>
             </Binding>
         </TextBox.Text>
     </TextBox>
     <TextBlock>Mouse-over to see the validation error message.</TextBlock>
 </StackPanel>

首先为文本框设置了键名为TextBoxInError的样式。

 <TextBox.Text>   
 <Binding Path="Age" Source="{StaticResource Data}"
          ValidatesOnExceptions="True"
          UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
                 <DataErrorValidationRule/>
      </Binding.ValidationRules>
             </Binding>
  </TextBox.Text>

ValidatesOnExceptions属性指定了是否在数据绑定过程中捕获并处理异常。ValidatesOnExceptions=“True”

表示如果在数据绑定过程中发生了异常(例如,数据源的Age属性在设置值时抛出了异常),这个异常将会被捕获并用于验证目的,通常用于显示错误信息或阻止无效数据的输入。

  <Binding.ValidationRules>
        <DataErrorValidationRule/>
  </Binding.ValidationRules>

Binding.ValidationRules是一个集合属性,用于存储数据绑定的验证规则。这些验证规则用于在数据绑定过程中检查数据的合法性。DataErrorValidationRule是WPF中预定义的一种验证规则。它用于检查数据对象是否实现了

IDataErrorInfo接口,并根据该接口提供的信息进行验证。当数据对象实现了IDataErrorInfo接口时,DataErrorValidationRule会调用接口中的方法来获取错误信息,并在数据绑定过程中应用这些错误信息。

验证类型

默认验证:当你输入 “a” 时,WPF尝试将 “a” 转换为整数,但由于 “a” 不是有效的整数,默认验证机制会生成一个错误,提示 “不是正确的格式”。

自定义验证:在你输入一个有效的整数后,WPF会继续检查这个值是否符合你的自定义验证规则(例如,年龄必须在0到150之间)。如果值不符合规则,你会看到 “Age must not be less than 0 or greater than 150” 的提示。

在WPF中,数据绑定的验证过程通常遵循以下顺序:

数据转换(Data Conversion)

如果绑定的数据需要从一种类型转换为另一种类型(例如,从字符串转换为整数),WPF会首先尝试进行类型转换。如果转换失败,会抛出一个异常,这个异常可以被捕获并用于验证目的。

验证规则(Validation Rules)

如果绑定的ValidationRules集合中定义了任何自定义的验证规则,WPF会按照这些规则的顺序依次执行它们。每个验证规则可以返回一个ValidationResult对象,指示数据是否有效以及相关的错误信息。

异常验证(Exception Validation)

如果绑定的ValidatesOnExceptions属性设置为True,WPF会在数据绑定的过程中捕获任何抛出的异常,并将这些异常转换为验证错误。这通常用于捕获数据转换或数据设置过程中的异常。

IDataErrorInfo 验证

如果数据对象实现了IDataErrorInfo接口,WPF会调用该接口的方法来获取错误信息。DataErrorValidationRule

可以用于在数据绑定过程中应用这些错误信息。

INotifyDataErrorInfo 验证

如果数据对象实现了INotifyDataErrorInfo接口,WPF会监听该接口的事件,并在数据发生错误时获取错误信息。这种验证方式提供了更灵活和异步的验证机制。

这些验证步骤并不是严格按顺序执行的,而是根据绑定的配置和数据对象的实现情况来决定。例如,如果绑定的

ValidationRules集合中包含了DataErrorValidationRule,那么IDataErrorInfo验证会在验证规则执行的过程中被触发。

WPF中的验证顺序是灵活的,并且可以根据具体的绑定配置和数据对象的实现情况来调整。通常情况下,数据转换和自定义验证规则会在异常验证和IDataErrorInfo验证之前执行。

代码来源

[WPF-Samples/Data Binding/BusinessLayerValidation at main · microsoft/WPF-Samples (github.com)](https://github.com/microsoft/WPF-Samples/tree/main/Data Binding/BusinessLayerValidation)

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

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

相关文章

初中英语优秀作文分析-006How to Deal with the Exam Stress-如何应对考试压力

更多资源请关注纽扣编程微信公众号 记忆树 1 We students are very busy with schoolwork and in the face of many exams every school day. 翻译 我们学生忙于功课&#xff0c;每个上学日都面临许多考试。 简化记忆 考试 句子结构 We students 主语 我们学生&#xf…

手把手教你入门vue+springboot开发(六)--后端代码解读与优化

文章目录 前言一、Lombok库二、spring-boot-starter-validation库三、ThreadLocalUtil四、全局异常处理总结 前言 前面我们已经把vuespringboot前后端分离开发和打包部署过程全部打通了&#xff0c;通过一个简单的demo来演示整个过程&#xff0c;主要关注在开发工具使用、框架…

CAD使用技巧,图片去边框,直线等分

CAD插入图片之后怎么去除图片边框 有时候我们需要将图片插入到CAD里面&#xff0c;但是发现插入进去之后&#xff0c;图片周围带有白色边框&#xff0c;这样看着就不是很舒服&#xff0c;要去除边框要如何操作呢 命令操作法&#xff1a;在命令栏输入“imageframe”回车&#xf…

蜜雪冰城小程序逆向

app和小程序算法一样 小程序是wasm

谈谈Flink消费kafka的偏移量

offset配置: flinkKafkaConsumer.setStartFromEarliest():从topic的最早offset位置开始处理数据&#xff0c;如果kafka中保存有消费者组的消费位置将被忽略。 flinkKafkaConsumer.setStartFromLatest():从topic的最新offset位置开始处理数据&#xff0c;如果kafka中保存有消费…

Golang | Leetcode Golang题解之第200题岛屿数量

题目&#xff1a; 题解&#xff1a; func numIslands(grid [][]byte) int {res : 0for i : 0; i < len(grid); i {for j : 0; j < len(grid[i]); j {if grid[i][j] 1 {resdfs(grid, i, j)}}}return res }func dfs(grid [][]byte, r, c int) {h, w : len(grid), len(gri…

C++感受12-Hello Object 派生版

不变的功能&#xff0c;希望直接复用原有代码&#xff1b;变化的功能&#xff0c;希望在分开的代码里实现。 派生的基本概念和目的如何定义派生类以及创建派生对象派生对象的生死过程 0. 课堂视频 ff14-HelloObject-派生版 1. 派生的基本概念与目的 编程&#xff0c;或者说软…

Games101学习笔记 Lecture 14: Ray Tracing 2 (Acceleration Radiometry)

Lecture 14: Ray Tracing 2 (Acceleration & Radiometry 一、加速光线追踪 AABB1.均匀网格 Uniform Spatial Partitions (Grids)①前处理-构建加速网格②射线与场景相交③网格分辨率④适用情况 2.空间划分KD-Tree①预处理②数据结构③遍历④问题 3.对象划分 & 包围盒层…

使用Python绘制极坐标图

使用Python绘制极坐标图 极坐标图极坐标图的优点使用场景 效果代码 极坐标图 极坐标图&#xff08;Polar Chart&#xff09;是一种图表类型&#xff0c;用于显示在极坐标系中的数据。极坐标图使用圆形坐标系&#xff0c;角度表示一个变量的值&#xff0c;半径表示另一个变量的…

森马基于MaxCompute+Hologres+DataWorks构建数据中台

讲师&#xff1a;晋银龙 浙江森马数仓高级经理 本次案例主要分享森马集团面对多年自建的多套数仓产品体系&#xff0c;通过阿里云MaxComputeHologresDataWorks统一数仓平台&#xff0c;保障数据生产稳定性与数据质量&#xff0c;减少ETL链路及计算时间&#xff0c;每年数仓整体…

Vue中的axios深度探索:从基础安装到高级功能应用的全面指南

文章目录 前言一、axios 请求1. axios的概念2. axios的安装3. axiso请求方式介绍4. axios请求本地数据5. axios跨域6. axios全局注册7. axios支持的请求类型1&#xff09;get请求2&#xff09;post请求3&#xff09;put请求4&#xff09;patch请求5&#xff09;delete请求 二、…

K8s的基本使用和认识

目录 介绍 控制端 Node(节点) 控制端与节点的关系图 基本使用 创建和运行资源 查找和参看资源 修改和删除资源 介绍 控制端 api-server(api)是集群的核心是k8s中最重要的组件,因为它是实现声明式api的关键 kubernetes api-server的核心功能是提供了Kubernetes各类资…

基于FreeRTOS+STM32CubeMX+LCD1602+MCP3008(SPI接口)的ADC转换器Proteus仿真

一、仿真原理图: 二、运行效果: 三、STM32CubeMX配置: 1)、RCC配置: 2)、SPI配置: 四、部分代码: 1)、主函数: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main…

mysql8.0.19安装zip版本

下载地址https://downloads.mysql.com/archives/community/ 下载版本 下载后解压&#xff0c;不包括data 和my.ini文件。其中data 文件是自动生成的【mysqld --initialize --console】&#xff0c;my.ini需要自己编写设置。 新建my.ini文件 需要自己设置 basedirG:\soft\mysql…

华为DCN网络之:VXLAN

VXLAN RFC定义了VLAN扩展方案VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff0c;虚拟扩展局域网&#xff09;。VXLAN采用MAC in UDP封装方式&#xff0c;是NVO3&#xff08;Network Virtualization over Layer 3&#xff09;中的一种网络虚拟化技术。 VXLAN…

android studio 添加aar包

按着以前旧的导包方式栽了大跟头&#xff0c;后面在留老板的的博客下找到了解决办法&#xff0c;记录一下。 Andriod Studio 导入aar最新的方式_gradle 8 引入arr-CSDN博客 最新导包方式 1.在新建libs目录&#xff0c;在app/libs目录下导入aar包&#xff08;其实就是拷贝过去…

hive4 从入门到精通

查询hive 架构 准备 HDFS配置 vim $HADOOP_HOME/etc/hadoop/core-site.xml <!--配置所有节点的root用户都可作为代理用户--><property><name>hadoop.proxyuser.root.hosts</name><value>*</value></property><!--配置root用户…

ETH巨鲸鱼异动和最大BTC爆仓

小编使用币界网地址监控工具&#xff0c;跟踪了在一次令人震惊的链上巨鲸地址异动&#xff0c;一个新创建的地址在过去四个小时内从 Coinbase 提取了价值 2121 万美元的 ETH。总共积累了 6,215 个 ETH&#xff0c;平均购买价格为每 ETH 3,414 美元。如此大规模的提款暗示着周一…

JVM原理(八):JVM虚拟机工具之基础故障工具

这里主要介绍监视虚拟机运行状态和进行故障处理的工具 1. jsp:虚拟机进程状况工具 jsp命令格式&#xff1a; jsp [options] [hostid] jps远程查询虚拟机进程状态 2. jstat:虚拟机统计信息监视工具 jstat命令格式&#xff1a; jstat [option vmid [interval [s|ms] [count]…