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. WPF 更改 DrawingVisual 的 RenderOpen 用到的对象的内容将持续影响渲染效果

    在 WPF 里面,可以通过 DrawingVisual 来进行使用底层的绘制方法,此方法需要调用 DrawingVisual 的 RenderOpen 拿到 DrawingContext 类型的对象, ...

  2. VGA显示文字

    VGA显示文字 VGA字符显示的原理 把要显示的字符转换成字符点阵,然后编码存储,着色的部分为1,其它为0.然后在VGA上输出显示. 字符点阵生成软件: https://www.zhetao.com/ ...

  3. CF522D Closest Equals 离线扫描 + 线段树

    CF522D Closest Equals 题意:m 个询问,求 [l,r] 内相同元素的最小距离. 离线询问,按右端点排序. 对于每一个 a[i],如果 last[a[i]] 存在,将线段树 las ...

  4. Fast Möbius Transform 学习笔记 | FMT

    小 Tips:在计算机语言中 \(\cap\) = & / and, \(\cup\) = | / or First. 定义 定义长度为 \(2^n\) 的序列的 and 卷积 \(A = B ...

  5. 随机化Tricks

    参阅: https://zh.cppreference.com/w/cpp/numeric/random https://zh.cppreference.com/w/cpp/header/random ...

  6. 深入 Django 模型层:数据库设计与 ORM 实践指南

    title: 深入 Django 模型层:数据库设计与 ORM 实践指南 date: 2024/5/3 18:25:33 updated: 2024/5/3 18:25:33 categories: ...

  7. Android项目自动生成uml图(以小米便签为例)

    摘要 最近在学习软件工程,需要完成小米便签的精读,任务中需要详细类图,由于项目巨大,手动画图打咩,试了一下午的android studio,试了诸如code iris,SequenceDigram(只 ...

  8. postgresql性能优化3:分区表

    一.分区表产生的背景 随着使用时间的增加,数据库中的数据量也不断增加,因此数据库查询越来越慢. 加速数据库的方法很多,如添加特定的索引,将日志目录换到单独的磁盘分区,调整数据库引擎的参数等.这些方法都 ...

  9. JDK源码阅读-------自学笔记(十六)(java.util.Random随机数类)

    Random类简介 如果使用Math.random()计算过于复杂的话,我们可以使用例外一种方式得到随机数,即Random类,这个类是专门用来生成随机数的,并且Math.random()底层调用的就是 ...

  10. PageOffice在线打开office文件通过js调用vba可实现的功能

    pageoffice封装的js接口有限,某些比较复杂的设置用到的客户不多,所以没有提供直接的js方法,但是pageoffice提供了Document属性和RunMacro方法,可以调vba或直接运行宏 ...