WPF入门教程系列三十 ——DataGrid验证
阅读原文时间:2023年07月10日阅读:1

WPF入门教程系列目录

WPF入门教程系列二——Application介绍

WPF入门教程系列三——Application介绍(续)

WPF入门教程系列四——Dispatcher介绍

WPF入门教程系列五——Window 介绍

WPF入门教程系列十一——依赖属性(一)

WPF入门教程系列十五——WPF中的数据绑定(一)

DataGrid 控件可以在单元格级别和行级别执行验证。 通过单元格级别验证,可以在用户修改单元的数据时验证绑定数据对象的单个属性。 通过行级别验证,可以在用户提交对行的更改时验证整行对象的数据。 还可以提供针对验证错误的自定义可视化反馈,或使用 DataGrid 控件提供的默认可视化反馈。

今天通过下面的示例学习如何将验证规则应用于 DataGrid 绑定并自定义可视化错误信息提示。

1. 在Visual Studio 2022的“解决方案资源管理器”中,使用鼠标右键单击“WpfGridDemo.NET7”项目,在弹出菜单中选择“添加-->新建文件夹”。 并将“新文件夹”改名为 “Vali”。

2. 在Visual Studio 2022的解决方案资源管理器中,使用鼠标右键单击“Vali”文件夹,在弹出菜单中选择“添加--> 类”,在弹出的“添加新项”对话框中,选择添加 “AreaValidationRule”类,这是一个我们要实现的验证类,然后选择“添加”。

3.要实现在自定交验证规则,则必须继承ValidationRule类,并重写Validate方法,下面就是具体实现代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using WpfGridDemo.NET7.Entitys;

namespace WpfGridDemo.NET7.Vali
{
public class AreaValidationRule: ValidationRule
{
public override ValidationResult Validate(object value,
System.Globalization.CultureInfo cultureInfo)
{
Area course = (value as BindingGroup).Items[0] as Area;
if (course.Created > course.Updated)
{

                return new ValidationResult(false,  
                    "创建日期必须小于等于更新日期。");  
            }  
            else  
            {  
                return ValidationResult.ValidResult;  
            }  
        }  
    }   

}

4. 创建提示信息的错误样式,当用户输入无效值时,提示信息样式将更改单元格背景色并添加工具提示。 请注意,使用触发器来确定是否存在验证错误。 此步骤是必需的,因为当前没有针对单元格的专用错误模板。错误样式代码:

5. 对DataGrid的DataGridTextColumn 绑定错误提示信息样式,设置ValidatesOnExceptions属性为true,此属性提供了显式使用元素的 ExceptionValidationRule替代方法。 ExceptionValidationRule是一个内置验证规则,用于检查在更新源属性期间引发的异常。

6.在Visual Studio 2022中按F5键,启动WPF应用程序。然后使用鼠标点击省份下拉框,界面中DataGrid中的呈现了城市与县区镇数据。

请尝试以下操作:

  • 在“ID”列中输入一个非整数值。
  • 删除“ID”的值。

你会发现,删除或是填了非整数值的那个单元格变成了红色,鼠标移到到其他单元格,也无法进入编辑模式。如下图。

7. 移动鼠标,将光标置入到红色的单元格中,然后按 ESC 键,应用程序自动撤消了无效的单元格值。如下图。

8.在Visual Studio 2022中打开MainWindows.xmal文件,并在文件的开头添加如下命名空间。

xmlns:vl="clr-namespace:WpfGridDemo.NET7.Vali"

9. 将之前创建的验证规则AreaValidationRule添加到 DataGrid.RowValidationRules 集合中。 以便通过 RowValidationRules 属性直接访问 BindingGroup 实例的 ValidationRules 属性,该实例对控件使用的所有绑定进行分组。

10. 通过设置 DataGrid.RowValidationErrorTemplate 属性,自定义各个 DataGrid 控件的行验证时的错误提示。 还可以使用隐式行样式设置 DataGridRow.ValidationErrorTemplate 属性来影响多个控件。

当用户输入无效值,行标题中将显示带有白色感叹号的红色圆圈。 行和单元格验证错误时都将发生这种情况。 关联的错误消息将显示在工具提示中。

        <DataGrid.RowValidationErrorTemplate>  
            <ControlTemplate>  
                <Grid Margin="0,-2,0,-2"

        ToolTip="{Binding RelativeSource={RelativeSource  
        FindAncestor, AncestorType={x:Type DataGridRow}},  
        Path=(Validation.Errors)\[0\].ErrorContent}">

                    <Ellipse StrokeThickness="0" Fill="Red"  
          Width="{TemplateBinding FontSize}"  
          Height="{TemplateBinding FontSize}" />  
                    <TextBlock Text="!" FontSize="{TemplateBinding FontSize}"  
          FontWeight="Bold" Foreground="White"  
          HorizontalAlignment="Center"  />  
                </Grid>  
            </ControlTemplate>  
        </DataGrid.RowValidationErrorTemplate>

11. 对DataGrid的DataGridTextColumn 绑定错误提示信息样式,设置ValidatesOnExceptions属性为true,此属性提供了显式使用元素的 ExceptionValidationRule替代方法。 ExceptionValidationRule是一个内置验证规则,用于检查在更新源属性期间引发的异常。


12. 在Visual Studio 2022中按F5键,启动WPF应用程序。然后使用鼠标点击省份下拉框,界面中DataGrid中的呈现了城市与县区镇数据。

请尝试以下操作:

  • 在“创建时间”列中输入一个早于更新时间的日期。
  • 删除“创建时间”或是“更新时间”单元格中的值

你会发现,删除了日期的那个单元格变成了红色,鼠标移到到其他单元格,也无法进入编辑模式。

你会发现,在行的行头中将显示一个红色感叹号 (!),将鼠标指针移到行标题中的标记上,以查看关联的错误消息。

如下图。

13.MainWindow.xmal的全部代码如下:





            <be:Interaction.Triggers>  
                <be:EventTrigger EventName="SelectionChanged">

                    <be:InvokeCommandAction Command="{Binding ProviceChangedAction}"   

CommandParameter="{Binding ElementName=cboProvince}"/>

        </ComboBox>  
    </WrapPanel>  
    <DataGrid x:Name="gridArea" Grid.Row="1" ItemsSource="{Binding GridAreaList}"  

AutoGenerateColumns="False" HorizontalAlignment="Left" VerticalAlignment="Top" SelectedItem="{Binding Path=AreaVM,
Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">

        <DataGrid.Resources>  
            <Style x:Key="errorStyle" TargetType="{x:Type TextBox}">  
                <Setter Property="Padding" Value="-2"/>  
                <Style.Triggers>  
                    <Trigger Property="Validation.HasError" Value="True">  
                        <Setter Property="Background" Value="Red"/>  
                        <Setter Property="ToolTip"  
      Value="{Binding RelativeSource={RelativeSource Self},  
        Path=(Validation.Errors)\[0\].ErrorContent}"/>  
                    </Trigger>  
                </Style.Triggers>  
            </Style>  
        </DataGrid.Resources>

        <DataGrid.Columns>  
            <DataGridComboBoxColumn Header="城市" Width="120"  x:Name="cboCity"   

ItemsSource="{x:Static v:MainWindowVM.GridCityList}"

ClipboardContentBinding="{x:Null}" SelectedValuePath="Code" SelectedValueBinding="{Binding Path=CityCode,
UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name" SelectedItemBinding="{x:Null}" />

            <DataGridComboBoxColumn Header="城市(Style)" SelectedValuePath="Code"   

SelectedValueBinding="{Binding Path=CityCode,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name" SelectedItemBinding="{x:Null}" Width="1*">








        <DataGrid.RowValidationRules>  
            <vl:AreaValidationRule ValidationStep="UpdatedValue"/>  
        </DataGrid.RowValidationRules>

        <DataGrid.RowValidationErrorTemplate>  
            <ControlTemplate>  
                <Grid Margin="0,-2,0,-2"

        ToolTip="{Binding RelativeSource={RelativeSource  
        FindAncestor, AncestorType={x:Type DataGridRow}},  
        Path=(Validation.Errors)\[0\].ErrorContent}">

                    <Ellipse StrokeThickness="0" Fill="Red"  
          Width="{TemplateBinding FontSize}"  
          Height="{TemplateBinding FontSize}" />

                    <TextBlock Text="!" FontSize="{TemplateBinding FontSize}"  
          FontWeight="Bold" Foreground="White"  
          HorizontalAlignment="Center"  />

                </Grid>  
            </ControlTemplate>  
        </DataGrid.RowValidationErrorTemplate>  
    </DataGrid>  
    <WrapPanel Grid.Row="2">

    <Button  x:Name="btnRefresh"  Height="22" Width="120" Click="btnRefresh\_Click">刷新</Button>  
        <Button  x:Name="btnSave" Height="22" Width="120" Command="{Binding ClickSaveAction}" >保存</Button>  
    </WrapPanel>  
</Grid>