BusinessLayerValidation介绍

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

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

在WPF中如何实现BusinessLayerValidation

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

该Demo结构如下所示:

实现的效果如下所示:

当输入值是字符时会提示不是正确的形式,当输入小于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)

WPF/C#:BusinessLayerValidation的更多相关文章

  1. WPF 3D:使用GeometryModel3D的BackMaterial

    原文 WPF 3D:使用GeometryModel3D的BackMaterial 使用BackMaterial,我们可以定义3D物体的内部材质(或者说是背面),比如,我们定义一个四方体容器,外面现实的 ...

  2. WPF 3D:MeshGeometry3D的定义和光照

    原文 WPF 3D:MeshGeometry3D的定义和光照 由于WPF计算光照会根据整个平面的方向向量,所以如果在不同面上使用同一个点可能会达到不同的光照效果.让我们用不同的定义Mesh的方法来演示 ...

  3. WPF 3D:使用变换中的TranslateTransform3D

    原文:WPF 3D:使用变换中的TranslateTransform3D 程序效果: WPF 3D中的TranslateTransform3D应该是所有3D变换中最简单的变换,使用起来非常简单,先定义 ...

  4. WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体

    原文:WPF 3D:简单的Point3D和Vector3D动画创造一个旋转的正方体 运行结果: 事实上很简单,定义好一个正方体,处理好纹理.关于MeshGeometry3D的正确定义和纹理这里就不多讲 ...

  5. WPF学习:3.Border & Brush

    上一章<WPF学习:2.Layout-Panels-Countainers>主要介绍了布局,容器和面板.这一章主要开始介绍Border(边界)和Brush(画刷). 代码地址:http:/ ...

  6. WPF编程:textbox控件文本框数据显示最后一行

    WPF编程:textbox控件文本框数据显示最后一行 TextBox控件在接收大量数据的时候,滚动条一般在最上方,如何使滚动条随着数据的接收而向下滚动呢?比如有一个TextBox'控件txbRecvD ...

  7. WPF 动画:同为控件不同命 - 简书

    原文:WPF 动画:同为控件不同命 - 简书 1. 及格与优秀 读大学的时候,有一门课的作业是用 PPT 展示. 但是我们很多同学都把 PPT 当做 Word 来用,就单纯地往里面堆文字. 大家都单纯 ...

  8. WPF优化:Freezable冻结对象

    原文:WPF优化:Freezable冻结对象 WPF虽然很美观,效果很炫,但是对资源的消耗也很大,尤其是初次接触WPF的人,因为很多地方虽然实现了想要的效果,但是由于经验问题,所以也会造成很大的资源浪 ...

  9. WPF学习:绑定

    原文 http://www.cnblogs.com/SouthAurora/archive/2010/06/30/1768464.html 一.绑定到元素对象 1.元素和元素(XAML.代码) 1.1 ...

  10. WPF教程:依赖属性

    一.什么是依赖属性 依赖属性就是一种自己可以没有值,并且可以通过绑定从其他数据源获取值.依赖属性可支持WPF中的样式设置.数据绑定.继承.动画及默认值. 将所有的属性都设置为依赖属性并不总是正确的解决 ...

随机推荐

  1. dotnet 读 WPF 源代码 聊聊 DispatcherTimer 的实现

    本文来告诉大家在 WPF 框架里面,是如何实现 DispatcherTimer 的功能.有小伙伴告诉我,读源代码系列的博客看不动,原因是太底层了.我尝试换一个方式切入逻辑,通过提问题和解决问题的方法, ...

  2. 云原生最佳实践系列 6:MSE 云原生网关使用 JWT 进行认证鉴权

    01 方案概述 MSE 网关可以为后端服务提供转发路由能力,在此基础上,一些敏感的后端服务需要特定认证授权的用户才能够访问.MSE 云原生网关致力于提供给云上用户体系化的安全解决方案,其中 JWT 认 ...

  3. 异常值检测算法三:3sigma模型

    离散度 标准差是反应一组数据离散程度最常用的一种量化形式,是表示精确度的重要指标.说起标准差首先得搞清楚它出现的目的.我们使用方法去检测它,但检测方法总是有误差的,所以检测值并不是其真实值.检测值与真 ...

  4. 火山引擎A/B测试平台的实验管理重构与DDD实践

    本次分享的主题是火山引擎数智平台VeDI旗下的A/B测试平台 DataTester 实验管理架构升级与DDD实践.这里说明的一点是,代码的第一目标肯定是满足产品需求,能够满足产品需求的代码都是好代码. ...

  5. BMP图片内部结构

    BMP图片内部结构 ​ BMP文件的数据按照从文件头开始的先后顺序分为四个部分:分别是位图文件头.位图信息头.调色板(24bit位图是没有的).位图数据(RGB). (1)位图文件头(Bitmap-F ...

  6. GitHub SSH 快速配置

    每次更换系统或者电脑时,都需要重新配置一番 Github SSH 的验证,记性不太好,写了一个快速部署的辅助脚本,直接安装脚本提示使用即可,经测试,Linux 和 Windows 下均能使用. 脚本功 ...

  7. liunx下redis的哨兵环境搭建

    哨兵简介 一定要有一个概念:哨兵实例也是特殊的Redis实例,也就是哨兵实例是独立的进程,多个哨兵实例可以搭建主从(Master-Slave),它们承担的职责和普通的Redis实例不一样.下面是官方文 ...

  8. Vue Vue-Router params 传参 为空 path定义参数 参数 param is not repeatable

    我在Vue-Router4.0.3版本上出现这个问题 因为官方 在2022年8月22日时废除了未定义的传参方式,所以必须使用定义的params. 解决办法: 在配置路由时:path路径上带上传值的ke ...

  9. 一文读懂Spring的SPI机制

    一. 从类加载说起 Java中的类加载器负载加载来自文件系统.网络或者其他来源的类文件.jvm的类加载器默认使用的是双亲委派模式.三种默认的类加载器Bootstrap ClassLoader.Exte ...

  10. 2024盘古石取证比赛(APK)

    题目列表 使用软件: Notepad++,火眼证据分析软件,雷电分析app,DB browser for SQLCipher 1. 分析伏季雅的手机检材,手机中诈骗APP的包名是:[答案格式:abc. ...