A newer version of this page is available. Switch to the current version.

Implementing ErrorInfo Support for Data Sources

  • 8 minutes to read

If the grid control is bound to a DataView or DataTable, you can set errors for any cell within any row using methods provided by the data source.

To set an error for a particular cell, you can call the SetColumnError method of a specific DataRow object. The grid control will indicate such errors by displaying error icons (ColumnView.SetColumnError_ErrorGlyph) within cells with the descriptions displayed as tooltips.

To support error notifications for any cell and row for other data source types (IList, ITypedList, IListSource, IBindingList, etc), you should implement the IDXDataErrorInfo or IDataErrorInfo interface for the objects representing records in your data source. This document gives you an example of implementing the IDataErrorInfo interface for a custom data source.

Note that the grid control provides methods to set errors for individual cells within the focused row and for the entire focused row. These methods can be applied regardless of the data source type. Usually you use these methods when validating the user's input via the BaseView.ValidateEditor and/or ColumnView.ValidateRow events. For more information, refer to the Internal ErrorInfo Support document.

Implementing the Error Notification Behavior

To bind a grid control to data created at runtime, you usually create two classes:

  • the class representing a data source; this implements one of interfaces (IList, IListSource, ITypedList, IBindingList) and provides access to the collection of records;
  • the class implementing a single record for a data source class.

If a data source supports error notifications, you are able to implement a validation procedure to verify data contained in the data source and, if invalid data is encountered, set errors for particular records and record's fields.

To support error notifications, the class encapsulating a single record must implement the IDataErrorInfo interface. This allows two members to get error descriptions for the entire record and for individual record's properties (data source fields). If a record object implements the interface, the grid control will display error icons within cells for which errors were set via the data source. Pointing to such an error icon displays a tooltip with an error description.

 

The GridUnboundErrorNotification tutorial (C:\Users\Public\Documents\DevExpress Demos 19.2\Components\WinForms\CS\GridTutorials\GridTutorials.csproj) shows how to implement the IDataErrorInfo interface for a custom data source.

The NoteInfo class represents a single record and provides the Day, Month, Year and NoteID fields displayed as columns in a grid control. This class implements the IDataErrorInfo interface and also introduces methods managing errors. It provides the SetColumnError, GetColumnError methods and NoteError property to get and set error descriptions for individual properties (Day, Month, Year and NoteID) and the entire record.

To clear a specific error, one should set the error to an empty string.

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
}

 

The ProjectNotes class manages a collection of NoteInfo objects and this represents a data source for a grid control. This class supports change notifications by implementing the IBindingList interface. When a new record is added or when record's properties and error descriptions are set, the IBindingList.ListChanged event is fired thus notifying the grid control that a particular record should be updated. You can refer to the Data Editing and Validation document for details on implementing data change notifications.

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
}

 

Data is validated within a custom ValidateData procedure. This traverses all records and checks the validity of data. If a record refers to an invalid date, an error is set for this record and for the date column where an error is encountered. The grid will indicate the errors with error icons as shown in the image below. Pointing to an icon displays a descriptive tooltip.

CD_IDataErrorInfo

//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);
        }   
    }
}

See the GridUnboundErrorNotification tutorial (C:\Users\Public\Documents\DevExpress Demos 19.2\Components\WinForms\CS\GridTutorials\GridTutorials.csproj) for the complete code.

See Also