如何:用 DataGrid 控件实现验证

如何:用 DataGrid 控件实现验证

.NET Framework 4.5
此主题尚未评级 评价此主题

利用 DataGrid 控件,您既可以在单元格级别也可以在行级别执行验证。 通过单元格级别验证,将可在用户更新值时验证绑定数据对象的个别属性。 通过行级别验证,将可在用户提交对行的更改时验证整个数据对象。 您也可以为验证错误提供自定义的可视反馈,或使用 DataGrid 控件提供的默认可视反馈。

以下过程介绍如何将验证规则应用于 DataGrid 绑定,并自定义可视反馈。

验证个别单元格值

  • 对用于列的绑定指定一条或多条验证规则。 这与在简单控件中验证数据类似,如数据绑定概述中所述。

    下面的示例显示一个 DataGrid 控件,其中包含绑定到业务对象的不同属性的四个列。 其中三个列通过将 ValidatesOnExceptions 属性设置为 true 来指定ExceptionValidationRule

    <Grid>
    
      <Grid.Resources>
        <local:Courses x:Key="courses"/>
      </Grid.Resources>
    
      <DataGrid Name="dataGrid1" FontSize="20"
        ItemsSource="{StaticResource courses}" 
        AutoGenerateColumns="False">
        <DataGrid.Columns>
          <DataGridTextColumn Header="Course Name" 
            Binding="{Binding Name, TargetNullValue=(enter a course name)}"/>
          <DataGridTextColumn Header="Course ID"
            Binding="{Binding Id, ValidatesOnExceptions=True}"/>
          <DataGridTextColumn Header="Start Date"
            Binding="{Binding StartDate, ValidatesOnExceptions=True, 
              StringFormat=d}"/>
          <DataGridTextColumn Header="End Date"
            Binding="{Binding EndDate, ValidatesOnExceptions=True,
              StringFormat=d}"/>
        </DataGrid.Columns>
      </DataGrid>
    
    </Grid>
    
    
    

    当用户输入无效的值,例如在“Course ID”(课程 ID)列中输入非整数时,单元格周围将出现一个红色边框。 可以按照下面过程中所述的方式更改此默认验证反馈。

自定义单元格验证反馈

  • 将列的 EditingElementStyle 属性设置为适合于列的编辑控件的样式。 由于编辑控件是在运行时创建的,因此您无法像处理简单控件一样使用Validation.ErrorTemplate 附加属性。

    下面的示例通过添加由具有验证规则的三个列共享的错误样式来更新前面的示例。 当用户输入无效的值时,样式会更改单元格背景颜色,并添加一个工具提示。 请注意使用触发器来确定是否存在验证错误的做法。 这是必要的,因为当前没有专门用于单元格的错误模板。

    <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>
    
    
    

    可通过替换列使用的 CellStyle 来实现更广泛的自定义。

验证单个行中的多个值

  1. 实现一个 ValidationRule 子类,该子类将检查绑定的数据对象的多个属性。 在 Validate 方法实现中,将 value 参数值强制转换为 BindingGroup 实例。 然后,即可通过 Items 属性访问数据对象。

    下面的示例演示此过程,以验证 Course 对象的 StartDate 属性值是否早于其 EndDate 属性值。

    C#
    VB
    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;
            }
        }
    }
    
    
    
  2. 将验证规则添加到 DataGrid.RowValidationRules 集合。 RowValidationRules 属性提供对 BindingGroup 实例的 ValidationRules 属性的直接访问,该实例对控件使用的所有绑定进行分组。

    下面的示例在 XAML 中设置 RowValidationRules 属性。 ValidationStep 属性设置为 UpdatedValue,以使验证只会在更新了绑定数据对象之后进行。

    <DataGrid.RowValidationRules>
      <local:CourseValidationRule ValidationStep="UpdatedValue"/>
    </DataGrid.RowValidationRules>
    
    
    

    当用户指定早于开始日期的结束日期时,行标题中将出现一个红色感叹号 (!)。 可以按照下面过程中所述的方式更改此默认验证反馈。

自定义行验证反馈

  • 设置 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>
    
    
    

下面的示例提供了单元格验证和行验证的完整演示。 Course 类提供了一个示例数据对象,该对象实现 IEditableObject 以支持事务。 DataGrid 控件与 IEditableObject交互,使用户能够通过按 Esc 来恢复更改。

说明 说明

如果使用的是 Visual Basic,请在 MainWindow.xaml 的第一行中将 x:Class="DataGridValidation.MainWindow" 替换为 x:Class="MainWindow"

若要测试验证,请尝试以下操作:

  • 在“Course ID”(课程 ID)列中,输入一个非整数值。

  • 在“End Date”(结束日期)列中,输入一个早于开始日期的日期。

  • 删除“Course ID”(课程 ID)、“Start Date”(开始日期)或“End Date”(结束日期)中的值。

  • 若要撤消无效的单元格值,请将光标重新放在单元格中,并按 Esc 键。

  • 若要在当前单元格处于编辑模式中时撤消整行的更改,请按 Esc 键两次。

  • 发生验证错误时,将鼠标指针移到行标题中的指示符上即可看到关联的错误消息。

VB
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


C#
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>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: GenericSQLGridActiveX_DataGrid是一种功能强大且灵活的控件,用于在应用程序中显示和编辑数据库表格的数据。它使用了Generic SQL作为数据源,并提供了许多功能和选项来自定义显示和处理数据。 首先,该控件支持使用Generic SQL语句来检索和修改数据。这意味着可以使用不同的SQL语句来满足不同的需求,如选择、插入、更新和删除数据。这给了开发人员更大的灵活性和控制权。 其次,该控件具有良好的数据展示和交互功能。用户可以通过表格方式查看和编辑数据,并可以执行排序、筛选和分页等功能。同时,还支持单元格级别的编辑,用户可以修改每个单元格的数据,并实时保存到数据库中。 此外,GenericSQLGridActiveX_DataGrid还提供了许多自定义选项,可以根据开发人员的需求进行配置。例如,可以设置列的可见性、宽度和排序方式。还可以定义特定列的输入验证规则,以确保数据的合法性。此外,还可以定义特定事件的处理方法,如数据变化、选中行变化等。 总之,GenericSQLGridActiveX_DataGrid控件提供了一个强大的工具,方便开发人员在应用程序中显示和编辑数据库表格的数据。它的灵活性和可定制性使得开发人员可以根据具体的需求进行配置和使用。使用该控件,可以轻松地实现数据库表格的展示和编辑功能。 ### 回答2: GenericSQLGrid ActiveX DataGrid是一个可以在Windows系统中使用的数据表格控件。它支持通用SQL查询语句,可以用于数据的展示和编辑。这个控件非常灵活,可以与各种数据库进行交互,并提供了许多功能和属性来定制和操作数据表格。 使用GenericSQLGrid ActiveX DataGrid控件,我们可以通过传入SQL查询语句来快速从数据库中检索数据,并将其显示在表格中。用户可以通过控件提供的功能来对数据进行排序、筛选和分页等操作,以便更方便地查看和分析数据。 此外,GenericSQLGrid ActiveX DataGrid控件还支持数据的编辑。用户可以直接在表格中修改数据,并通过特定的事件和方法将修改后的数据保存回数据库中。这使得数据的编辑和重用变得极为方便。 该控件还提供了灵活的界面定制选项,用户可以通过修改样式和设置不同的属性来自定义表格的外观和行为。用户可以对列进行排序和分组,更改列的宽度和顺序,并添加自定义按钮和菜单等。 总的来说,GenericSQLGrid ActiveX DataGrid控件是一个功能强大、灵活易用的数据表格控件,可以有效地处理和展示各种数据库中的数据。无论是用于简单的数据查询还是复杂的数据分析和编辑,该控件都能提供良好的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值