WPF DataGrid 控件的数据验证

在开发过程中,经常需要对数据进行验证,以确保数据的准确性和完整性。本文将介绍如何在.NET Framework 3.5及以上版本中使用WPF Toolkit的DataGrid控件进行数据验证。WPF Toolkit是一个开源的WPF控件集合,提供了许多实用的控件,其中就包括DataGrid。DataGrid是一个强大的数据展示和编辑控件,支持数据绑定、排序、筛选等高级功能。

在本例中,将使用MVVM模式进行开发。MVVM是一种设计模式,用于分离视图(View)和模型(Model)的逻辑,使得代码更加清晰和易于维护。在MVVM模式中,视图负责展示数据,模型负责存储数据,而视图模型(ViewModel)则负责处理视图和模型之间的交互逻辑。

最近,需要在一个表格控件中验证数据。不想购买第三方组件,而是决定使用WPF Toolkit的DataGrid。在阅读了Colin Eberhardt的优秀文章后,意识到在.NET Framework 3.5中使用时,尤其是当数据不是由用户更改而是通过程序添加时,会遇到一些问题。需要实现一个小工具,可以通过解压缩Zip文件进行部署。因此,不想让用户仅仅为了解决验证问题而需要安装.NET Framework 4.0。

使用代码

应用程序使用MVVM模式。如果还没有听说过它,建议阅读Josh Smith的好文章。验证发生的地方是一个名为PersonVM的类。这个类包含以下属性: string FirstName string LastName bool HasJob (string JobName) 需要验证两件事:首先,名字和姓氏只能包含A-Za-z字符和空格。其次,不允许一个人设置HasJob标志,但JobName为空,或者反之。

第一条规则可以通过验证每个名称属性来检查。要检查第二条规则,仅仅验证一个属性是不够的,而是需要多个属性。这种验证发生在整个Person对象上。

验证是在以下PersonVM索引器中实现的(由IDataError接口所需): public string this[string columnName] { get { // apply property level validation rules if (columnName == "FirstName") { if (String.IsNullOrEmpty(this.FirstName)) return "First Name needs to be filled"; if (!MyNameEx.Match(this.FirstName).Success) return "First Name may only contain characters or spaces"; } if (columnName == "LastName") { if (String.IsNullOrEmpty(this.LastName)) return "Last Name needs to be filled"; if (!MyNameEx.Match(this.LastName).Success) return "Last Name may only contain characters or spaces"; } // Method ValidateJob applies object level validation. In this example the consistency // of the properties HasJob and JobName is checked on object level. An error is // announced for JobName only. Otherwise the red error border would be presented for // the JobName and the HasJob field and the error correction would be inconvenient // for the user - try it out by uncommenting following line if (columnName == "JobName" || columnName == "HasJob") if (columnName == "JobName") { return ValidateJob(); } return ""; } }

ValidateJob方法如下: private string ValidateJob() { if (!this.HasJob && !String.IsNullOrEmpty(this.JobName)) { return "Job Name is given, but Job Flag is not set!"; } if (this.HasJob && String.IsNullOrEmpty(this.JobName)) { return "Job Name is not given, but Job Flag is set!"; } return ""; }

IDataError的第二种方法没有为PersonVM单独编写,可以放入一个基类或帮助类中。

多字段验证需要通过一个字段来通知 - 例如示例中的JobName - 因为用户不能在一步中编辑多个字段来纠正多字段错误。因此,当HasJob复选框更新时,需要模拟JobName已更改。这种通知是在HasJob setter中完成的: public Boolean HasJob { get { return myHasJob; } set { myHasJob = value; NotifyPropertyChanged("JobName"); NotifyErrorChanged(); } }

XAML代码

DataGrid的相应XAML代码如下: <Window x:Class="ValidationInWpfDatagrid.View.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition Height="20"/> </Grid.RowDefinitions> <dg:DataGrid Name="myDataGrid" AutoGenerateColumns="False" ItemsSource="{Binding PersonList}" CanUserAddRows="True"> <dg:DataGrid.Resources> <Style TargetType="{x:Type dg:DataGridCell}"> <Setter Property="TextBlock.ToolTip" Value="{Binding Error}"/> </Style> </dg:DataGrid.Resources> <dg:DataGrid.Columns> <dg:DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName, ValidatesOnDataErrors=True}" Width="*"/> <dg:DataGridTextColumn Header="LastName" Binding="{Binding Path=LastName, ValidatesOnDataErrors=True}" Width="*"/> <dg:DataGridCheckBoxColumn Header="Job Flag" Binding="{Binding Path=HasJob, ValidatesOnDataErrors=True}" Width="*"/> <dg:DataGridTextColumn Header="Job's Name" Binding="{Binding Path=JobName, ValidatesOnDataErrors=True}" Width="*"/> </dg:DataGrid.Columns> </dg:DataGrid> <Button Grid.Row="1" Name="myBtnAddPerson" Content="Add Person" Command="{Binding AddPersonCommand}"/> </Grid> </Window>

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485