Back to Devexpress

Error Notification Support for Data Sources

windowsforms-751-controls-and-libraries-data-grid-data-editing-and-validation-errorinfo-support-error-notification-support-for-data-sources.md

latest10.6 KB
Original Source

Error Notification Support for Data Sources

  • Jul 22, 2025
  • 5 minutes to read

Error Notifications for DataTable and DataView

If your data source is a DataView or DataTable, you can indicate invalid values in any row at the data source level, using the DataRow.SetColumnError method. The grid control will display error icons ( ) within cells that contain these errors. When you hover with the mouse cursor over the error icons, the grid shows tooltips containing error text.

Error Notifications for Custom Data Sources

To support error notifications for custom data sources, implement the IDataErrorInfo or IDXDataErrorInfo interface for your business object (the class that encapsulates records).

Tip

The grid control has methods to set errors for the focused row and its individual cells. These methods are supported for all data source types, even if they do not implement the IDataErrorInfo or IDXDataErrorInfo interface. For more information, refer to the Internal ErrorInfo Support document.

Example

The following example implements the IDataErrorInfo interface to support error notifications for a business object (Customer). Errors are raised if the Customer.FirstName or Customer.LastName fields are empty.

The GridControl automatically displays error icons for cells with invalid values. To display error icons in standalone editors, assign the DXErrorProvider to a data source.

csharp
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.DXErrorProvider;
using DevExpress.XtraGrid;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

namespace DXApplication19 {
    public partial class Form1 : DevExpress.XtraEditors.XtraForm {
        public Form1() {
            InitializeComponent();

            GridControl gridControl1 = new GridControl();
            Controls.Add(gridControl1);
            gridControl1.Dock = DockStyle.Fill;

            //Create a data source
            BindingList<Customer> list = new BindingList<Customer>();
            list.Add(new Customer("Andrew", "Weber"));
            list.Add(new Customer("", "Kovar")); // An invalid first name
            list.Add(new Customer("Kathy", "")); // An invalid last name

            BindingSource bindingSource1 = new BindingSource(list, "");
            gridControl1.DataSource = bindingSource1;

            // To show data source errors in standalone editors, bind a DXErrorProvider to the data source.
            DXErrorProvider dxErrorProvider1 = new DXErrorProvider(this);
            dxErrorProvider1.DataSource = bindingSource1;

            // Create a TextEdit control and bind it to the First Name field
            TextEdit textEdit1 = new TextEdit();
            textEdit1.DataBindings.Add(new Binding("EditValue", bindingSource1, "FirstName"));

            LabelControl label = new LabelControl();
            label.Padding = new Padding(0, 30, 0, 5);
            label.Text = "TextEdit bound to FirstName field:";

            Controls.Add(label);
            label.Dock = DockStyle.Bottom;

            Controls.Add(textEdit1);
            textEdit1.Dock = DockStyle.Bottom;

        }
    }

    public class Customer: IDataErrorInfo, INotifyPropertyChanged {
        public Customer(string firstName, string lastName) {
            FirstName = firstName;
            LastName = lastName;

        }
        string firstName;
        public string FirstName {
            get {
                return firstName;
            }
            set {
                ValidateValue(value);
                firstName = value;
                OnPropertyChanged();
            }
        }

        string lastName;
        public string LastName {
            get {
                return lastName;
            }
            set {
                ValidateValue(value);
                lastName = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public virtual void OnPropertyChanged([CallerMemberName] String propertyName = "") {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        // Stores errors for all properties of the Customer class.
        Dictionary<string, string> PropertyErrors = new Dictionary<string, string>();
        string IDataErrorInfo.this[string propertyName] {
            get {
                string errorText;
                return PropertyErrors.TryGetValue(propertyName, out errorText) ? errorText : null;
            }
        }
        string IDataErrorInfo.Error => string.Empty;

        // Clears or sets errors for the FirstName and LastName fields.
        void ValidateValue(string value, [CallerMemberName] String propertyName="") {
            bool isValid = !string.IsNullOrEmpty(value);
            if (isValid) {
                //Clear a previous error, if any.
                PropertyErrors.Remove(propertyName);
            }
            else {
                //Set an error.
                string errorText = propertyName + " is required";
                PropertyErrors[propertyName] = errorText;
            }
        }

    }
}
vb
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Imports DevExpress.XtraEditors
Imports DevExpress.XtraEditors.DXErrorProvider
Imports DevExpress.XtraGrid

Partial Public Class Form1
    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim gridControl1 As GridControl = New GridControl()
        Controls.Add(gridControl1)
        gridControl1.Dock = DockStyle.Fill

        'Create a data source
        Dim list As BindingList(Of Customer) = New BindingList(Of Customer)()
        list.Add(New Customer("Andrew", "Weber"))
        list.Add(New Customer("", "Kovar")) ' An invalid first name
        list.Add(New Customer("Kathy", "")) ' An invalid last name

        Dim bindingSource1 As BindingSource = New BindingSource(list, "")
        gridControl1.DataSource = bindingSource1

        ' To show data source errors in standalone editors, bind a DXErrorProvider to the data source.
        Dim dxErrorProvider1 As New DXErrorProvider(Me)
        dxErrorProvider1.DataSource = bindingSource1

        ' Create a TextEdit control and bind it to the First Name field
        Dim textEdit1 As TextEdit = New TextEdit()
        textEdit1.DataBindings.Add(New Binding("EditValue", bindingSource1, "FirstName"))

        Dim label As LabelControl = New LabelControl()
        label.Padding = New Padding(0, 30, 0, 5)
        label.Text = "TextEdit bound to FirstName field:"

        Controls.Add(label)
        label.Dock = DockStyle.Bottom

        Controls.Add(textEdit1)
        textEdit1.Dock = DockStyle.Bottom
    End Sub
End Class

Public Class Customer
    Implements IDataErrorInfo, INotifyPropertyChanged
    Public Sub New(ByVal firstName_Renamed As String, ByVal lastName_Renamed As String)
        Me.FirstName = firstName_Renamed
        Me.LastName = lastName_Renamed

    End Sub
    Private firstName_Renamed As String
    Public Property FirstName() As String
        Get
            Return firstName_Renamed
        End Get
        Set
            ValidateValue(Value)
            firstName_Renamed = Value
            OnPropertyChanged()
        End Set
    End Property

    Private lastName_Renamed As String
    Public Property LastName() As String
        Get
            Return lastName_Renamed
        End Get
        Set
            ValidateValue(Value)
            lastName_Renamed = Value
            OnPropertyChanged()
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
    Public Overridable Sub OnPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub

    ' Stores errors for all properties of the Customer class.
    Private PropertyErrors As Dictionary(Of String, String) = New Dictionary(Of String, String)()
    Private ReadOnly Property Item(ByVal propertyName As String) As String Implements IDataErrorInfo.Item
        Get
            Dim errorText As String = ""
            If PropertyErrors.TryGetValue(propertyName, errorText) Then
                Return errorText
            Else
                Return Nothing
            End If
        End Get
    End Property

    Private ReadOnly Property [Error] As String Implements IDataErrorInfo.Error
        Get
            Return ""
        End Get
    End Property

    Private Sub ValidateValue(ByVal value As String, <CallerMemberName> ByVal Optional propertyName As String = Nothing)
        Dim isValid As Boolean = Not String.IsNullOrEmpty(value)
        If isValid Then
            'Clear a previous error, if any.
            PropertyErrors.Remove(propertyName)
        Else
            'Set an error.
            Dim errorText As String = propertyName & " is required"
            PropertyErrors(propertyName) = errorText
        End If
    End Sub
End Class

See Also

Edit Data. Create Cell Editors. Validate User Input

Internal ErrorInfo Support

Tutorial: Data Input Validation

Data Binding