分类:
如何:用 DataGrid 控件实现验证
利用 DataGrid 控件,您既可以在单元格级别也可以在行级别执行验证。 通过单元格级别验证,将可在用户更新值时验证绑定数据对象的个别属性。 通过行级别验证,将可在用户提交对行的更改时验证整个数据对象。 您也可以为验证错误提供自定义的可视反馈,或使用 DataGrid 控件提供的默认可视反馈。 以下过程介绍如何将验证规则应用于 DataGrid 绑定,并自定义可视反馈。 验证个别单元格值
自定义单元格验证反馈
验证单个行中的多个值
自定义行验证反馈
下面的示例提供了单元格验证和行验证的完整演示。 Course 类提供了一个示例数据对象,该对象实现 IEditableObject 以支持事务。 DataGrid 控件与 IEditableObject交互,使用户能够通过按 Esc 来恢复更改。
若要测试验证,请尝试以下操作:
Imports System.Collections.ObjectModel Imports System.ComponentModel Public Class MainWindow Private Sub dataGrid1_InitializingNewItem(ByVal sender As System.Object, _ ByVal e As System.Windows.Controls.InitializingNewItemEventArgs) _ Handles dataGrid1.InitializingNewItem Dim newCourse As Course = CType(e.NewItem, Course) newCourse.StartDate = DateTime.Today newCourse.EndDate = DateTime.Today End Sub End Class Public Class Courses Inherits ObservableCollection(Of Course) Sub New() Me.Add(New Course With { _ .Name = "Learning WPF", _ .Id = 1001, _ .StartDate = New DateTime(2010, 1, 11), _ .EndDate = New DateTime(2010, 1, 22) _ }) Me.Add(New Course With { _ .Name = "Learning Silverlight", _ .Id = 1002, _ .StartDate = New DateTime(2010, 1, 25), _ .EndDate = New DateTime(2010, 2, 5) _ }) Me.Add(New Course With { _ .Name = "Learning Expression Blend", _ .Id = 1003, _ .StartDate = New DateTime(2010, 2, 8), _ .EndDate = New DateTime(2010, 2, 19) _ }) Me.Add(New Course With { _ .Name = "Learning LINQ", _ .Id = 1004, _ .StartDate = New DateTime(2010, 2, 22), _ .EndDate = New DateTime(2010, 3, 5) _ }) End Sub End Class Public Class Course Implements IEditableObject, INotifyPropertyChanged Private _name As String Public Property Name As String Get Return _name End Get Set(ByVal value As String) If _name = value Then Return _name = value OnPropertyChanged("Name") End Set End Property Private _number As Integer Public Property Id As Integer Get Return _number End Get Set(ByVal value As Integer) If _number = value Then Return _number = value OnPropertyChanged("Id") End Set End Property Private _startDate As DateTime Public Property StartDate As DateTime Get Return _startDate End Get Set(ByVal value As DateTime) If _startDate = value Then Return _startDate = value OnPropertyChanged("StartDate") End Set End Property Private _endDate As DateTime Public Property EndDate As DateTime Get Return _endDate End Get Set(ByVal value As DateTime) If _endDate = value Then Return _endDate = value OnPropertyChanged("EndDate") End Set End Property #Region "IEditableObject" Private backupCopy As Course Private inEdit As Boolean Public Sub BeginEdit() Implements IEditableObject.BeginEdit If inEdit Then Return inEdit = True backupCopy = CType(Me.MemberwiseClone(), Course) End Sub Public Sub CancelEdit() Implements IEditableObject.CancelEdit If Not inEdit Then Return inEdit = False Me.Name = backupCopy.Name Me.Id = backupCopy.Id Me.StartDate = backupCopy.StartDate Me.EndDate = backupCopy.EndDate End Sub Public Sub EndEdit() Implements IEditableObject.EndEdit If Not inEdit Then Return inEdit = False backupCopy = Nothing End Sub #End Region #Region "INotifyPropertyChanged" Public Event PropertyChanged As PropertyChangedEventHandler _ Implements INotifyPropertyChanged.PropertyChanged Private Sub OnPropertyChanged(ByVal propertyName As String) RaiseEvent PropertyChanged(Me, _ New PropertyChangedEventArgs(propertyName)) End Sub #End Region End Class Public Class CourseValidationRule Inherits ValidationRule Public Overrides Function Validate(ByVal value As Object, _ ByVal cultureInfo As System.Globalization.CultureInfo) _ As ValidationResult Dim course As Course = _ CType(CType(value, BindingGroup).Items(0), Course) If course.StartDate > course.EndDate Then Return New ValidationResult(False, _ "Start Date must be earlier than End Date.") Else Return ValidationResult.ValidResult End If End Function End Class using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; namespace DataGridValidation { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); dataGrid1.InitializingNewItem += (sender, e) => { Course newCourse = e.NewItem as Course; newCourse.StartDate = newCourse.EndDate = DateTime.Today; }; } } public class Courses : ObservableCollection<Course> { public Courses() { this.Add(new Course { Name = "Learning WPF", Id = 1001, StartDate = new DateTime(2010, 1, 11), EndDate = new DateTime(2010, 1, 22) }); this.Add(new Course { Name = "Learning Silverlight", Id = 1002, StartDate = new DateTime(2010, 1, 25), EndDate = new DateTime(2010, 2, 5) }); this.Add(new Course { Name = "Learning Expression Blend", Id = 1003, StartDate = new DateTime(2010, 2, 8), EndDate = new DateTime(2010, 2, 19) }); this.Add(new Course { Name = "Learning LINQ", Id = 1004, StartDate = new DateTime(2010, 2, 22), EndDate = new DateTime(2010, 3, 5) }); } } public class Course : IEditableObject, INotifyPropertyChanged { private string _name; public string Name { get { return _name; } set { if (_name == value) return; _name = value; OnPropertyChanged("Name"); } } private int _number; public int Id { get { return _number; } set { if (_number == value) return; _number = value; OnPropertyChanged("Id"); } } private DateTime _startDate; public DateTime StartDate { get { return _startDate; } set { if (_startDate == value) return; _startDate = value; OnPropertyChanged("StartDate"); } } private DateTime _endDate; public DateTime EndDate { get { return _endDate; } set { if (_endDate == value) return; _endDate = value; OnPropertyChanged("EndDate"); } } #region IEditableObject private Course backupCopy; private bool inEdit; public void BeginEdit() { if (inEdit) return; inEdit = true; backupCopy = this.MemberwiseClone() as Course; } public void CancelEdit() { if (!inEdit) return; inEdit = false; this.Name = backupCopy.Name; this.Id = backupCopy.Id; this.StartDate = backupCopy.StartDate; this.EndDate = backupCopy.EndDate; } public void EndEdit() { if (!inEdit) return; inEdit = false; backupCopy = null; } #endregion #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } #endregion } public class CourseValidationRule : ValidationRule { public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { Course course = (value as BindingGroup).Items[0] as Course; if (course.StartDate > course.EndDate) { return new ValidationResult(false, "Start Date must be earlier than End Date."); } else { return ValidationResult.ValidResult; } } } } <Window x:Class="DataGridValidation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:DataGridValidation" Title="DataGrid Validation Example" Height="240" Width="600"> <Grid> <Grid.Resources> <local:Courses x:Key="courses"/> </Grid.Resources> <DataGrid Name="dataGrid1" FontSize="20" RowHeaderWidth="27" ItemsSource="{StaticResource courses}" AutoGenerateColumns="False"> <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> <DataGridTextColumn Header="Course Name" Binding="{Binding Name, TargetNullValue=(enter a course name)}"/> <DataGridTextColumn Header="Course ID" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding Id, ValidatesOnExceptions=True}"/> <DataGridTextColumn Header="Start Date" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding StartDate, ValidatesOnExceptions=True, StringFormat=d}"/> <DataGridTextColumn Header="End Date" EditingElementStyle="{StaticResource errorStyle}" Binding="{Binding EndDate, ValidatesOnExceptions=True, StringFormat=d}"/> </DataGrid.Columns> <DataGrid.RowValidationRules> <local:CourseValidationRule 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> </Grid> </Window> |
|