Error Notification Support for Data Sources

  • 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 (ColumnView.SetColumnError_ErrorGlyph) 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 shows how to support error notifications for a business object (a Customer class) via the IDataErrorInfo interface. Errors are raised if the Customer.FirstName or Customer.LastName fields are empty.

A GridControl automatically shows error icons for these cells. To show error icons in standalone editors, the DXErrorProvider is bound to the data source.

ColumnView.SetColumnError_ErrorGlyph

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

    }
}

More Examples

You can find additional examples in the ‘GridUnboundErrorNotification’ and ‘GridUnboundErrorNotificationAdv’ tutorials located at C:\Users\Public\Documents\DevExpress Demos 21.1\Components\WinForms\CS\GridTutorials\ and C:\Users\Public\Documents\DevExpress Demos 21.1\Components\WinForms\VB\GridTutorials.

See Also