如果网格控件被绑定到 DataView 或 DataTable,则可以使用数据源提供的方法,为任何行中的任何单元格设置错误。 要为特定单元格设置错误,可以调用特定 DataRow 对象的 DataRow.SetColumnError 方法。 通过在单元格内显示一个错误图标 (),网格控件将指明这个错误,在错误图标的工具提示中显示错误说明。
要为其他数据源类型 (IList、ITypedList、IListSource、IBindingList 等等) 中的任何单元格和行支持错误通知,则应该为数据源中表示记录的对象实现 IDXDataErrorInfo 或 IDataErrorInfo 接口。 本文档提供了一个为自定义数据源实现 IDataErrorInfo 接口的示例。
注意,网格控件提供了方法来为获得焦点的整个行及其个别单元格设置错误。 这些方法可以被应用,而不管数据源的类型。 通常,当通过 BaseView.ValidateEditor 和/或 ColumnView.ValidateRow 事件来验证最终用户的输入时使用这些方法。 更多信息,请参阅 内部 ErrorInfo 支持 文档。
实现错误通知的行为
要把网格控件绑定到在运行时刻创建的数据,通常要创建两个类:
- 表示数据源的类。 实现其中一种接口 (IList、IListSource、ITypedList、IBindingList) 并提供对记录集合的访问。
- 为数据源类实现单条记录的类。
如果数据源支持错误通知,则可以实现验证程序,来校验包含在数据源中的数据,如果遇到了无效数据,则为特定的记录和记录字段设置错误。
要支持错误通知,则封装单条记录的类必须实现 IDataErrorInfo 接口。 此接口提供了两个成员,来为整条记录及个别记录的属性 (数据源字段) 获取错误说明。 如果记录对象实现了此接口,则网格控件将在单元格内显示错误图标,指明通过数据源设置了错误的单元格。 鼠标指针指向该错误图标时,会显示一条含有错误说明的工具提示。
GridUnboundErrorNotification 的指南展示了如何为自定义数据源实现 IDataErrorInfo 接口。
NoteInfo 类表示单条记录,并提供了在网格控件中显示为列的 Day、Month、 Year 和 NoteID 字段。 该类实现了 IDataErrorInfo 接口,也提供了管理错误的方法。 它提供了 SetColumnError、GetColumnError 方法和 NoteError 属性来获取和设置个别属性 (Day、Month、Year 和 NoteID) 及整条记录的错误说明。
要清除特定的错误,只需要把错误说明设置为空字符串。C# | 复制代码 |
---|---|
using System.ComponentModel; public class NoteInfo : System.ComponentModel.IDataErrorInfo { //... //Stores error descriptions for the Day, Month, Year and NoteID properties Hashtable propertyErrors; //Stores an error description for the item string noteError; public NoteInfo(int _noteID, int _day, int _month, int _year) { //... //Set errors to empty strings propertyErrors = new Hashtable(); propertyErrors.Add("Day", ""); propertyErrors.Add("Month", ""); propertyErrors.Add("Year", ""); propertyErrors.Add("NoteID", ""); noteError = ""; } public int NoteID { /*...*/ } public int Day { /*...*/ } public int Month { /*...*/ } public int Year { /*...*/ } //Gets and sets an error for the current item internal string NoteError { get { return noteError; } set { if(noteError == value) return; noteError = value; OnNoteChanged(); } } public void ClearErrors() { SetColumnError("Day", ""); SetColumnError("Month", ""); SetColumnError("Year", ""); NoteError = ""; } //Sets an error for an item's property public void SetColumnError(string elem, string error) { if(propertyErrors.ContainsKey(elem)) { if((string)propertyErrors[elem] == error) return; propertyErrors[elem] = error; OnNoteChanged(); } } //Gets an error for an item's property public string GetColumnError(string elem) { if(propertyErrors.ContainsKey(elem)) return (string)propertyErrors[elem]; else return ""; } //The owner collection internal ProjectNotes Owner { /*...*/ } //Notify the owner collection about record changing protected void OnNoteChanged() { if(Owner != null) Owner.OnRecordChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, Owner.IndexOf(this))); } #region IDataErrorInfo Members //Returns an error description set for the item's property string IDataErrorInfo.this[string columnName] { get { return GetColumnError(columnName); } } //Returns an error description set for the current item string IDataErrorInfo.Error { get { return noteError; } } #endregion } |
Visual Basic | 复制代码 |
---|---|
Imports System.ComponentModel Public Class NoteInfo Implements System.ComponentModel.IDataErrorInfo '... 'Stores error descriptions for the Day, Month, Year and NoteID properties Dim propertyErrors As Hashtable 'Stores an error description for the item Dim _noteError As String Public Sub New(ByVal _noteID As Integer, ByVal _day As Integer, _ ByVal _month As Integer, ByVal _year As Integer) '... 'Set errors to empty strings propertyErrors = New Hashtable() propertyErrors.Add("Day", "") propertyErrors.Add("Month", "") propertyErrors.Add("Year", "") propertyErrors.Add("NoteID", "") _noteError = "" End Sub Public Property NoteID() As Integer '... End Property Public Property Day() As Integer '... End Property Public Property Month() As Integer '... End Property Public Property Year() As Integer '... End Property 'Gets and sets an error for the current item Friend Property NoteError() As String Get Return _noteError End Get Set(ByVal Value As String) If _noteError = Value Then Return _noteError = Value OnNoteChanged() End Set End Property Public Sub ClearErrors() SetColumnError("Day", "") SetColumnError("Month", "") SetColumnError("Year", "") NoteError = "" End Sub 'Sets an error for an item's property Public Sub SetColumnError(ByVal elem As String, ByVal _error As String) If propertyErrors.ContainsKey(elem) Then If CType(propertyErrors(elem), String) = _error Then Return propertyErrors(elem) = _error OnNoteChanged() End If End Sub 'Gets an error for an item's property Public Function GetColumnError(ByVal elem As String) As String If propertyErrors.ContainsKey(elem) Then Return propertyErrors(elem) Else Return "" End If End Function 'The owner collection Friend Property Owner() As ProjectNotes '... End Property 'Notify the owner collection about record changing Protected Sub OnNoteChanged() If Not Owner Is Nothing Then Owner.OnRecordChanged(New ListChangedEventArgs(_ ListChangedType.ItemChanged, Owner.IndexOf(Me))) End Sub #Region " IDataErrorInfo Members " 'Returns an error description set for the current item Friend ReadOnly Property [Error]() As String _ Implements System.ComponentModel.IDataErrorInfo.Error Get Return NoteError End Get End Property 'Returns an error description set for the item's property Default Public ReadOnly Property Item(ByVal columnName As String) As String _ Implements System.ComponentModel.IDataErrorInfo.Item Get Return GetColumnError(columnName) End Get End Property #EndRegion End Class |
ProjectNotes 类管理 NoteInfo 对象的一个集合,并表示网格控件的一个数据源。 该类通过实现 IBindingList 接口,支持更改通知。 当新记录被添加,或当记录的属性和错误说明被设置时, IBindingList.ListChanged 事件发生,因而通知网格控件应该更新特定的记录。 可以参阅 刷新网格控件 文档获得关于实现数据更改通知的细节。
C# | 复制代码 |
---|---|
public class ProjectNotes: CollectionBase, IBindingList { //... //Adds a new item to the collection public int Add(NoteInfo nInfo) { int index = List.Add(nInfo); return index; } //Fires the IBindingList.ListChanged event. protected internal void OnRecordChanged(ListChangedEventArgs e) { if(ListChanged != null) ListChanged(this, e); } #region IBindingList Members // ... #endregion } |
Visual Basic | 复制代码 |
---|---|
Public Class ProjectNotes Inherits CollectionBase Implements IBindingList '... 'Adds a new item to the collection Public Function Add(ByVal nInfo As NoteInfo) As Integer Dim index As Integer = List.Add(nInfo) Return index End Function 'Fires the IBindingList.ListChanged event Protected Friend Sub OnRecordChanged(ByVal e As ListChangedEventArgs) RaiseEvent ListChanged(Me, e) End Sub #Region "IBindingList Members " ' ... #EndRegion End Class |
在自定义的 ValidateData 程序内验证数据。 它遍历所有记录,并检查数据的有效性。 如果某条记录引用了无效的日期,则为该记录设置错误,并且为遇到错误的数据列设置错误。 网格控件将使用错误图标指明错误,如下图所示。 当鼠标指针指向错误图标时,显示一条有错误说明的工具提示:
C# | 复制代码 |
---|---|
//Returns the name of the date property containing invalid data private string IsValidDate(int day, int month, int year) { if(month < 1 || month > 12) return "Month"; if(day < 1 || day > DateTime.DaysInMonth(year, month)) return "Day"; if(year < 1980 || year > 2010) return "Year"; return ""; } private void ValidateData() { ProjectNotes notes = gridControl1.DataSource as ProjectNotes; foreach(NoteInfo nInfo in notes) { string valid = IsValidDate(nInfo.Day, nInfo.Month, nInfo.Year); nInfo.ClearErrors(); if(valid != "") { nInfo.NoteError = "Check the date"; nInfo.SetColumnError(valid, "Invalid " + valid); } } } |
Visual Basic | 复制代码 |
---|---|
'Returns the name of the date property containing invalid data private string IsValidDate(int day, int month, int year) { if(month < 1 || month > 12) return "Month"; if(day < 1 || day > DateTime.DaysInMonth(year, month)) return "Day"; if(year < 1980 || year > 2010) return "Year"; return ""; } private void ValidateData() { ProjectNotes notes = gridControl1.DataSource as ProjectNotes; foreach(NoteInfo nInfo in notes) { string valid = IsValidDate(nInfo.Day, nInfo.Month, nInfo.Year); nInfo.ClearErrors(); if(valid != "") { nInfo.NoteError = "Check the date"; nInfo.SetColumnError(valid, "Invalid " + valid); } } } |