Skip to main content

Edit Data. Create Cell Editors. Validate User Input

  • 31 minutes to read

Get and Modify Cell Values in Code

Important

Use the following methods only when the Grid and its columns are fully initialized. If you need to call these methods while the form is still loading, call the ForceInitialize() method to force the Grid to finish its initialization.

Processed Cell

Read the Cell Value

Change the Cell Value

A focused cell

ColumnView.GetFocusedValue
ColumnView.FocusedValue

ColumnView.SetFocusedValue

A cell of a focused row

ColumnView.GetFocusedRowCellValue
ColumnView.GetFocusedRowCellDisplayText

ColumnView.SetFocusedRowCellValue

Any row cell

ColumnView.GetRowCellValue
ColumnView.GetRowCellDisplayText

ColumnView.SetRowCellValue

A cell value in an underlying data source

ColumnView.GetListSourceRowCellValue

The currently edited cell

ColumnView.EditingValue

ColumnView.EditingValue

The ColumnView.CellValueChanging and ColumnView.CellValueChanged events are raised when a user changes a cell value.

Example 1 - Get cell values

The code snippet below retrieves the value of a cell that belongs to the “ID” column and the third data row (row handle equals 2).

string cellValue;
cellValue = gridView1.GetRowCellValue(2, "ID").ToString();
Example 2 - Get the focused cell text

This code sample returns text displayed inside the currently focused cell.

string cellValue = gridView1.GetFocusedDisplayText();
Example 3 - Change the focused cell value

This example changes the value of the focused cell.

gridView1.SetRowCellValue(gridView1.FocusedRowHandle, gridView1.FocusedColumn, "New Value");
//or
gridView1.SetFocusedValue("New Value");
Example 4 - Post edit values immediately

A grid cell editor waits for a user to move focus to another cell or row before its new value is accepted. The code sample below forces editors to update their values immediately.

    BaseEdit edit = null;
    private void gridView1_ShownEditor(object sender, EventArgs e)
    {
        GridView view = sender as GridView;
        edit = view.ActiveEditor;
        edit.EditValueChanged += edit_EditValueChanged;       
    }

    void edit_EditValueChanged(object sender, EventArgs e)
    {
        gridView1.PostEditor();
    }

    private void gridView1_HiddenEditor(object sender, EventArgs e)
    {
        edit.EditValueChanged -= edit_EditValueChanged;
        edit = null;
    }
Example 5 - Auto-adjust cell values

In the Change column cell values based on another column’s values demo, checkboxes under the “Mark” column are automatically checked if you enter a “Length” of more than 10, or cleared otherwise.

gridView.CellValueChanged += (sender, e) => {
    GridView view = sender as GridView;
    if (e.Column.FieldName == "Length") {
        double doubleVal = (double)e.Value;
        view.SetRowCellValue(e.RowHandle, "Mark", doubleVal > 10);
    }
};

Note

  • In a Data Grid that is bound to a master-detail source, detail data is stored in Clone Views, not Pattern Views. Use the GridView.GetDetailView method to obtain a Clone View. Use clone view GetCellValue or GetRow methods to obtain its cell values and data rows. Read the following topic for more information: How to Work with Master-Detail Relationships in Code.
  • You cannot obtain or modify cell values until there is a row object that corresponds to a record. If a user adds rows with New Item Row, the Data Grid initializes new row objects for these rows only after the user modifies a cell.

Modify Unbound Column Values

Unbound Columns display calculated or custom data. Handle the ColumnView.CustomUnboundColumnData event and use the e.IsSetData parameter to implement editing in an unbound column.

The following example creates an editable unbound column. The “unboundData” dictionary supplies data to the column.

using DevExpress.XtraGrid.Columns;
using DevExpress.XtraGrid.Views.Base;

Dictionary<int, int> unboundData = new Dictionary<int, int>();
void Form1_Shown(object sender, EventArgs e) {
    // Create an unbound column
    GridColumn UnboundCol = new GridColumn();
    UnboundCol.UnboundDataType = typeof(int);
    UnboundCol.FieldName = "Custom";
    UnboundCol.Visible = true;
    gridView1.Columns.Add(UnboundCol);
}
void gridView1_CustomUnboundColumnData(object sender, CustomColumnDataEventArgs e) {
    if (e.Column.FieldName == "Custom") {
        // Populate the column with values
        if (e.IsGetData)
            e.Value = unboundData.ContainsKey(e.ListSourceRowIndex) ? unboundData[e.ListSourceRowIndex] : 0;
        // Save user input
        if (e.IsSetData && e.Value != null)
            unboundData[e.ListSourceRowIndex] = (int)e.Value;
    }
}

Run Demo: How to Edit Unbound Columns

Cell Editors

Difference between Repository Items and Real Editors

A data editor is a UI control. A repository item is an object that contains the settings required for a container control (for example, the Data Grid) to create a cell editor.

All DevExpress Data Editors have corresponding repository items. For instance, a RepositoryItemSpinEdit object is a repository item for SpinEdit. Use the editor’s Properties property to access its repository item.

Repository Items and Data Editors - WinForms Data Grid

Grid cells contain repository items. When a user clicks a cell to edit its value, the Grid uses repository item settings to create a cell editor. After the user has finished editing the cell value and has moved focus, the Grid destroys the cell’s editor. A cell editor (active editor) exists only when the Grid is in edit mode. This technique improves Grid performance.

The following example demonstrates how to access the active editor within Grid View and clear its value:

if(gridView1.ActiveEditor != null) {
    gridView1.ActiveEditor.EditValue = null;
}

Default Cell Editors

Grid columns use data editors to display and edit data. Columns automatically create editors depending on the type of data they display. For example, a column that displays date-time values uses the DateEdit.

Data Grid - Date Edit In-Place Editor

Run Demo: Cell Editors Run Demo: Show Buttons in Cells

Data Type Default Editor and Repository Item
String, Numeric, TimeOnly TextEdit, RepositoryItemTextEdit
Boolean CheckEdit, RepositoryItemCheckEdit
Date-Time, DateOnly DateEdit, RepositoryItemDateEdit
DateTimeOffset DateTimeOffsetEdit, RepositoryItemDateTimeOffsetEdit
TimeSpan TimeSpanEdit, RepositoryItemTimeSpanEdit
Enumeration ComboBoxEdit, RepositoryItemComboBox
Picture/Image PictureEdit, RepositoryItemPictureEdit

Replace Default Cell Editors at Design Time

Invoke a column’s smart tag menu and use the GridColumn.ColumnEdit property’s dropdown to create a new editor or choose an existing editor.

Data Grid - Column Edit Smart Tag

You can also run the Data Grid Designer and open its In-place Editor Repository page to access all in-place editors. You can add, customize, and remove repository items.

Data Grid - Repository Items Designer

Create Cell Editors and Assign Them to Columns in Code

Create a repository item, add it to the Grid’s RepositoryItems collection, and assign the repository item to the GridColumn.ColumnEdit property.

    // Creates a 'ToggleSwitch' repository item.            
    RepositoryItemToggleSwitch edit = new RepositoryItemToggleSwitch();
    // Adds the repository item to the grid's RepositoryItems collection. 
    gridControl.RepositoryItems.Add(edit);
    // Assigns the repository item to the 'Mark' column.
    gridView.Columns["Mark"].ColumnEdit = edit;
How to display a progress bar in a column with numeric values

The code snippet below illustrates how to utilize a ProgressBarControl as an in-place editor for the integer “Relevance” grid column. Users can tap or hold numpad “+” and “-“ keys to modify these integer values.

using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraEditors.Repository;

// Create a repository item
RepositoryItemProgressBar ieProgress = new RepositoryItemProgressBar();
gridControl1.RepositoryItems.Add(ieProgress);
ieProgress.KeyPress += IeProgress_KeyPress;

// Assign the repository item
colRelevance.ColumnEdit = ieProgress;
// Or
private void GridView1_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e) {
    if (e.Column == colRelevance) e.RepositoryItem = ieProgress;
}

// Handle + and - key presses
private void IeProgress_KeyPress(object sender, KeyPressEventArgs e) {
    int i = 0;
    if (gridView1.ActiveEditor == null) return;

    if (e.KeyChar == '+') {
        i = (int)gridView1.ActiveEditor.EditValue;
        if (i < 100)
            gridView1.ActiveEditor.EditValue = i + 1;
    }
    if (e.KeyChar == '-') {
        i = (int)gridView1.ActiveEditor.EditValue;
        if (i > 0)
            gridView1.ActiveEditor.EditValue = i - 1;
    }
}
How to display buttons in cells

The Cell commands to edit and delete rows demo has a “Commands” column with a ButtonEdit cell editor. This editor has two buttons: Edit invokes the Edit Form, and Delete removes the current row.

buttonEdit

    // Create the Commands column editor
    RepositoryItemButtonEdit commandsEdit = new RepositoryItemButtonEdit { AutoHeight = false, Name = "CommandsEdit", TextEditStyle = TextEditStyles.HideTextEditor };
    commandsEdit.Buttons.Clear();
    commandsEdit.Buttons.AddRange(new EditorButton[] {
    new EditorButton(ButtonPredefines.Glyph, "Edit", -1, true, true, false, ImageLocation.MiddleLeft, DemoHelper.GetEditImage()),
    new EditorButton(ButtonPredefines.Glyph, "Delete", -1, true, true, false, ImageLocation.MiddleLeft, DemoHelper.GetDeleteImage())});
    grid.RepositoryItems.Add(commandsEdit);

    // Create an unbound Commands column
    GridColumn _commandsColumn = gridView.Columns.AddField("Commands");
    _commandsColumn.UnboundDataType = typeof(object);
    _commandsColumn.Visible = true;
    _commandsColumn.Width = 100;

    // Hide commandsColumn from EditForm
    _commandsColumn.OptionsEditForm.Visible = DevExpress.Utils.DefaultBoolean.False;

    // Display commands only for the focused row
    gridView.CustomRowCellEdit += (s, e) => {
        if (e.RowHandle == gridView.FocusedRowHandle && e.Column == _commandsColumn)
            e.RepositoryItem = commandsEdit;
    };
    gridView.CustomRowCellEditForEditing += (s, e) => {
        if (e.RowHandle == gridView.FocusedRowHandle && e.Column == _commandsColumn)
            e.RepositoryItem = commandsEdit;
    };

    // Allow only commandsColumn to be edited
    gridView.ShowingEditor += (s, e) => {
        e.Cancel = gridView.FocusedColumn != _commandsColumn;
    };

    gridView.OptionsEditForm.ShowOnDoubleClick = DevExpress.Utils.DefaultBoolean.False;
    gridView.OptionsEditForm.ShowOnEnterKey = DevExpress.Utils.DefaultBoolean.False;
    gridView.OptionsEditForm.ShowOnF2Key = DevExpress.Utils.DefaultBoolean.False;
    gridView.OptionsBehavior.EditingMode = GridEditingMode.EditFormInplace;

    // Perform a specific action when an EditorButton is clicked
    commandsEdit.ButtonClick += (s, e) => {
        switch (e.Button.Caption) {
            case "Edit":
                // Start editing a row using EditForm
                gridView.CloseEditor();
                gridView.ShowEditForm();
                break;
            case "Delete":
                // Delete focused row
                gridView1.DeleteRow(gridView1.FocusedRowHandle);
                break;
        }
    };
How to use different editors for cells of the same column

In the Assign in-place editors dynamically demo, the “Length” column receives either a SpinEdit or a CalcEdit editor depending on whether the checkbox under the “Mark” column is checked.

RepositoryItemSpinEdit spinEdit = new RepositoryItemSpinEdit();
RepositoryItemCalcEdit calcEdit = new RepositoryItemCalcEdit();
grid.RepositoryItems.Add(spinEdit);
grid.RepositoryItems.Add(calcEdit);
gridView.Columns["Length"].ShowButtonMode = ShowButtonModeEnum.ShowAlways;

// Handle this event to assign editors to individual cells
gridView.CustomRowCellEdit += (sender, e) => {
    GridView view = sender as GridView;
    if (e.Column.FieldName == "Length") {
        bool boolVal = (bool)view.GetRowCellValue(e.RowHandle, "Mark");
        if (boolVal)
            e.RepositoryItem = spinEdit;
        else
            e.RepositoryItem = calcEdit;
    }
};

Assign Different Editors to Cells in a Column

Handle the GridView.CustomRowCellEdit event to specify a specific in-place editor for a certain cell or a group of cells.

using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraEditors.Repository;

public Form1() {
    InitializeComponent();
    // Creates the repository items.
    RepositoryItem spinEdit = new RepositoryItemSpinEdit();
    RepositoryItem calcEdit = new RepositoryItemCalcEdit();
    // Adds the repository items to the grid's RepositoryItems collection.
    gridControl1.RepositoryItems.AddRange(new RepositoryItem[] { spinEdit, calcEdit });
    /* Handles the 'CustomRowCellEdit' event to assign different editors to cells
    * in the 'Length' column.
    */
    gridView1.CustomRowCellEdit += (sender, e) => {
        GridView view = sender as GridView;
        if(e.Column.FieldName == "Length")
            e.RepositoryItem = (bool)view.GetRowCellValue(e.RowHandle, "Mark") ? spinEdit : calcEdit;
    };
}

Run Demo: Cell Editors Run Demo: Disable Buttons in Certain Rows

Display Any UI Control in Grid Cells

Use RepositoryItemAnyControl to embed a UI control into a grid cell. The control must implement the DevExpress.XtraEditors.CustomEditor.IAnyControlEdit interface. The DevExpress Gauge Control and Chart Control implement this interface out of the box. You need to implement this interface manually to embed other UI controls in grid cells.

The image below shows the grid cell with an embedded DevExpress Chart control.

Data Grid - In-Place Chart Control

Run Demo: Embedded Gantt Run Demo: Embedded Chart

How to Display DevExpress Gantt Control in Grid Cells

Use Different Editors to Display and Edit Cell Values

A column uses the same editor to display and edit its values. Handle the CustomRowCellEditForEditing event to use different editors to display and edit column values.

The following example demonstrates how to use ProgressBarControl to display numeric values in the Quantity column, and SpinEdit to edit cell values.

using DevExpress.XtraEditors.Repository;

public Form1() {
    InitializeComponent();
    // Creates two repository items.
    RepositoryItem editorForDisplay, editorForEditing;
    // Initializes the repository items.
    editorForDisplay = new RepositoryItemProgressBar();
    editorForEditing = new RepositoryItemSpinEdit();
    // Forces the grid to initialize its settings.
    gridControl1.ForceInitialize();
    // Adds the repository items to the grid's RepositoryItems collection.
    gridView1.GridControl.RepositoryItems.AddRange(
        new RepositoryItem[] { editorForDisplay, editorForEditing });
    // Assign the 'Progress Bar' repository item to the numeric 'Quantity' column.
    gridView1.Columns["Quantity"].ColumnEdit = editorForDisplay;
    /* Handles the 'CustomRowCellEditForEditing' event to create a Spin Editor
        * when a user edits a cell value in the 'Quantity' column.
        */
    gridView1.CustomRowCellEditForEditing += (sender, e) => {
        if(e.Column.FieldName == "Quantity")
            e.RepositoryItem = editorForEditing;
    };
}

Run Demo: Use Different In-place Editors for Certain Cells

API to Manage Cell Editors

API

Description

BaseView.ShowEditor

Invokes the focused cell’s editor.

BaseView.HideEditor

Closes the active editor and discards the changes made.

BaseView.CloseEditor

Saves any changes made and closes the active editor.

BaseView.PostEditor

Saves any changes made without closing the active editor.

BaseView.ActiveEditor

Gets the active editor.

ColumnView.ShownEditor

Fires when the grid activates an in-place editor.

The following example shows how to specify the current date and open the DateEdit‘s dropdown when the user starts to edit a value in the OrderDate column.

using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;

private void GridView1_ShownEditor(object sender, EventArgs e) {
    GridView view = sender as GridView;
    if (view.FocusedColumn == colOrderDate) {
        // Specifies the current date.
        view.EditingValue = DateTime.Today;
        // Gets the active editor.
        DateEdit editor = view.ActiveEditor as DateEdit;
        // Invokes the dropdown.
        editor.ShowPopup();
    }
}

ColumnView.HiddenEditor

Fires when an in-place editor closes.

The following example demonstrates how to move cell focus to the next cell in a column after the active editor has been closed. A user does not need to move focus from one cell to another to edit cell values in a column.

using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;

private void GridView1_HiddenEditor(object sender, EventArgs e) {
    GridView view = sender as GridView;
    if (view.FocusedRowHandle == GridControl.NewItemRowHandle) return;
    if (view.FocusedRowHandle == view.RowCount - 1)
        view.FocusedRowHandle = 0;
    else
        view.FocusedRowHandle++;
    view.ShowEditor();
}

OptionsBehavior.EditorShowMode

Specifies how a cell editor is activated by the mouse.

The following example shows how to always display editor buttons and let users click editor buttons on the first click:

Editor Show Mode - WinForms Data Grid, DevExpress

using DevExpress.Utils;
using DevExpress.XtraGrid.Views.Base;

private void Form1_Load(object sender, EventArgs e) {
    gridView1.OptionsBehavior.EditorShowMode = EditorShowMode.MouseDown;
    gridView1.OptionsView.ShowButtonMode = ShowButtonModeEnum.ShowAlways;
}

Disable Certain Cells (Cell Editors)

Disable All Cells

Disable a View’s OptionsBehavior.Editable option to disable all cells in the View.

gridView1.OptionsBehavior.Editable = false;

Disable Cells in a Column

Disable a column’s OptionsColumn.AllowEdit to disable its cells.

gridView1.OptionsBehavior.Editable = true;
// Disables cells displayed in the PropertyA column.
gridView1.Columns["PropertyA"].OptionsColumn.AllowEdit = false;

Enable a column’s OptionsColumn.ReadOnly setting to make its cells read-only (the OptionsColumn.AllowEdit property must be set to true). The user can invoke the cell’s editor to copy its value, but cannot edit that value.

gridView1.OptionsBehavior.Editable = true;
gridView1.Columns["PropertyA"].OptionsColumn.AllowEdit = true;
// Makes cells in the PropertyA column read-only.
gridView1.Columns["PropertyA"].OptionsColumn.ReadOnly = true;

Run Demo: Disabled Mode

Disable Cells and Rows Based on a Condition

Use one of the following options to disable specific cells or data rows based on a condition:

  • Handle the ColumnView.ShowingEditor event and set the e.Cancel parameter to true to disable the processed cell based on a specific condition.

    The following example handles the ShowingEditor event to disable cells in the focused row if the value in the Country column is “Germany”:

    using DevExpress.XtraGrid.Views.Grid;
    
    private void gridView1_ShowingEditor(object sender, System.ComponentModel.CancelEventArgs e) {
       GridView view = sender as GridView;
       string cellValue = view.GetRowCellValue(view.FocusedRowHandle, colCountry).ToString();
       e.Cancel = cellValue == "Germany";
    }
    

    The following example prevents users from editing cells in the “ID” column in odd rows (the example makes cells read-only):

    gridView.ShownEditor += (s, e) => {
        GridView view = s as GridView;
        view.ActiveEditor.Properties.ReadOnly =
            gridView.FocusedColumn.FieldName == "ID" && gridView.FocusedRowHandle % 2 == 0;
    };
    
  • Use the Disabled Cell Behavior to disable cells in rows that meet a specific condition. Disabled cells are grayed-out and cannot be edited.

Run Demo: Read-Only Mode for Certain Cells

Disable Edit Form Fields Based on a Condition

Use one of the following techniques to disable fields in the Edit Form:

  • Handle the GridView.EditFormPrepared event. Use the e.BindableControls property to access the required editor and disable its Editable property.
  • Create a Custom Edit Form and specify the behavior of editors in EditFormUserControl.

Edit Data in a Separate Form

Edit Form Modes

Users can use an Edit Form instead of in-place editors to edit data rows. Double-click a grid row or press the Enter or F2 key to invoke the Edit Form. Use the EditingMode property to specify the edit mode.

Data Grid - Inline Edit Form

Grid-based Views support the following Edit Form display modes:

  • Floating Modal Form (default)
  • Inline Edit Form with Data Row (the grid displays the Edit Form below the edited data row)
  • Inline Edit Form (the grid does not display the edited row)

Run Demo: Inline Edit Form Run Demo: Access Editor in Edit Form

Note

Detail Views in Master-Detail Mode do not support in-line edit forms.

Edit Form API

API

Description

GridOptionsBehavior.EditingMode

Allows you to turn on the Edit Form and specify its display mode.

GridView.ShowEditForm
GridView.HideEditForm

Allow you to display and hide the Edit Form.

GridOptionsEditForm.ActionOnModifiedRowChange

Specifies whether to show confirmation dialogs when users modify records.

GridOptionsEditForm.ShowUpdateCancelPanel

Specifies whether to display the Update and Cancel buttons. Ctrl+Enter saves the changes. Esc discards the changes.

GridOptionsEditForm.BindingMode

Specifies whether to pass changes to the Grid immediately after a user moves focus to another field in the Edit Form, or after all changes have been accepted.

GridOptionsEditForm.FormCaptionFormat

Specifies the caption of a Floating Edit Form.

GridView.EditFormShowing

Fires before the Edit Form is displayed. Handle this event to hide the Edit Form and prevent a user from editing values in certain cells.

The following example prevents a user from editing cell values in even rows:

gridView.OptionsBehavior.EditingMode = GridEditingMode.EditForm;

gridView1.EditFormShowing += (s, e) => {
    e.Allow = e.RowHandle % 2 != 0; 
};

Run Demo

Important

The Edit Form uses the Tag property of repository items internally. Do not set the Tag property to avoid runtime issues.

Change Values in Edit Form Fields — Implement Custom Edit Logic

The Edit Form is a container control with data editors (fields). Data editors are bound to corresponding fields/properties in a data record. Do one of the following to specify values of these data editors:

The following example handles the EditFormPrepared event to focus the ‘first’ Date Editor when a user opens the Edit Form.

using DevExpress.XtraGrid.Views.Grid;

// ...
gridView.OptionsBehavior.EditingMode = GridEditingMode.EditForm;

DateEdit dateEdit = null;
gridView.EditFormPrepared += (s, e) => {
    // The 'e.BindableControls' collection contains the editors in the Edit Form.
    foreach (Control item in e.BindableControls) {
        dateEdit = item as DateEdit;
        if (dateEdit != null) {
            // Focuses the Date Editor.
            dateEdit.Select();
            return;
        }
    }
};

Run Demo: How to Access Editor in Edit Form

Note

Handle the EditFormHidden event to remove references to Edit Form editors and unsubscribe from event handlers.

Tip

This guideline is applicable to other DevExpress Data-Aware Controls that support Edit Forms: Gantt Control, Tree List, etc.

Change Edit Form Layout

The Grid control creates the Edit Form according to the following rules:

  • An Edit Form displays an editor for every visible editable column.
  • If a column uses different editors to edit and display cell values, an Edit Form displays the editors used in Edit mode.
  • An Edit Form’s client area has a table layout with three columns. Each editor (except for MemoEdit and PictureEdit ) occupies a single cell in the table.
  • MemoEdit editors span across all layout columns horizontally and three layout rows vertically.
  • PictureEdit editors span across two layout columns horizontally and three layout rows vertically.

Tip

Invoke the Data Grid Designer and switch to the EditForm Designer page to customize the layout of the Edit Form.

Data Grid - Edit Form Designer

Edit Form API

API

Description

GridColumn.OptionsEditForm

Use this property to customize a column’s editor displayed in the Edit Form.

OptionsColumnEditForm.UseEditorColRowSpan

Disable this option to set custom column and row spans for a column’s editor.

OptionsColumnEditForm.ColumnSpan / OptionsColumnEditForm.RowSpan

Specify the number columns and rows across which a column’s editor spans.

OptionsColumnEditForm.Caption / OptionsColumnEditForm.CaptionLocation

Allow you to specify the editor’s caption and its position.

OptionsColumnEditForm.Visible / OptionsColumnEditForm.VisibleIndex

Use these properties to hide the editor or specify its position among other editors.

OptionsColumnEditForm.StartNewRow

Enable this option to display the editor on a new line.

Create Custom Edit Form

  1. Create a User Control. Inherit it from the EditFormUserControl class. If you have partial classes for a User Control, they must also inherit the EditFormUserControl class.
  2. Create the Edit Form UI (customize the User Control as needed).
  3. Use SetBoundFieldName and SetBoundPropertyName methods of the parent class to bind the editors to data source fields.
  4. Assign an instance of the Custom Edit Form to the Grid’s GridOptionsEditForm.CustomEditFormLayout property.
  5. Assign separate instances of the Custom Edit Form to each detail View to use the Custom Edit Form in detail views in Master-Detail Mode.
using DevExpress.XtraGrid.Views.Grid;
// Custom Edit Form
public class AdvancedEditForm : EditFormUserControl {
    public AdvancedEditForm() {
        InitializeComponent();
        // Binds the 'EditValue' of the 'textEdit3' editor to the Price field.
        this.SetBoundFieldName(textEdit3, "Price");
        this.SetBoundPropertyName(textEdit3, "EditValue");
    }
}

// Enables the Custom Edit Form.
gridView1.OptionsEditForm.CustomEditFormLayout = new AdvancedEditForm();

// Enables the Custom Edit Form to edit values in detail views in Master-Detail mode.
void gridControl1_ViewRegistered(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e) {
    GridView detailCloneView = e.View as GridView;
    if(detailCloneView.LevelName == "Order_Details")
        detailCloneView.OptionsEditForm.CustomEditFormLayout = new AdvancedEditForm(); 
}

Run Demo: Custom Edit Form

Manage User Input

Use Predefined and Custom Masks

Input Masks define the way in which data can be entered within an application to help you get intuitive and error-free data input. The following example demonstrates how to specify a 10-digit phone mask.

var settings = repositoryItemTextEdit1.MaskSettings.Configure<MaskSettings.Numeric>();
settings.MaskExpression = "+1 (000) 000-0000";
repositoryItemTextEdit1.UseMaskAsDisplayFormat = true; // Optional
grid.RepositoryItems.Add(repositoryItemTextEdit1);
gridView.Columns["Phone"].ColumnEdit = repositoryItemTextEdit1;

Validate Cells

The Data Grid automatically validates a cell’s value when a user presses Enter or moves focus to another cell in the same row. Use the BaseView.PostEditor method to forcibly validate cell value.

The following diagram illustrates how the grid validates cell values:

Data Grid - Validation - Cell Validation

  • BaseView.ValidatingEditor - Handle this event to check whether a new value is correct. Set the e.Valid parameter accordingly. Users cannot move focus away from a cell with an invalid value until it is corrected or until the Esc key is pressed to cancel the change.
  • BaseView.InvalidValueException - A view raises this event if the e.Valid parameter in the ValidatingEditor event handler has been set to false. This event allows you to specify how the Data Grid responds to an invalid value (ExceptionMode).
  • If the e.ExceptionMode parameter is set to NoAction, a cell does not accept an invalid value and the Grid does not display any notifications. You need to manually notify the user of invalid input. For example, use the ColumnView.SetColumnError method to display error icons.
  • Handle the GridView.RowCellStyle event to highlight cells with invalid values.

Run Demo: Data Validation Run Demo: Validate Active Editor

How to compare cell values

The code sample below checks the order shipping date to ensure that it is not earlier than the date this order was placed.

Data Grid - Validation Dates

private void GridView1_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e) {
    GridView view = sender as GridView;
    if (view.FocusedColumn == colRequiredDate) {
        DateTime? requiredDate = e.Value as DateTime?;
        DateTime? orderDate = view.GetRowCellValue(view.FocusedRowHandle, colOrderDate) as DateTime?;
        if (requiredDate < orderDate) {
            e.Valid = false;
            e.ErrorText = "Required Date is earlier than the order date";
        }
    }
}
How to avoid duplicate values

The following code sample from the Prevent entering duplicate values demo illustrates how to check “ID” column values and prevent users from entering repeating IDs.

gridView.ValidatingEditor += (s, e) => {
    string fieldName = string.Empty;
    GridView view = s as GridView;
    EditFormValidateEditorEventArgs ea = e as EditFormValidateEditorEventArgs;
    if(ea == null)
        fieldName = view.FocusedColumn.FieldName;
    else
        fieldName = ea.Column.FieldName;
    int rowCellValue;
    int validatingCellValue = Convert.ToInt32(e.Value);
    if(fieldName == "ID")
        // Iterate through all data rows within GridView
        for(int rowHandle = 0; rowHandle < view.DataRowCount; rowHandle++) {
            // Obtain the ID cell value of the processed row
            rowCellValue = Convert.ToInt32(view.GetRowCellValue(rowHandle, fieldName)); 
            if(rowCellValue == validatingCellValue) {
                e.Valid = false;
                e.ErrorText = "ID should be unique (ValidatingEditor)";
                return;
            }
        }
};

gridView.InvalidValueException += (s, e) => {
    e.ExceptionMode = ExceptionMode.DisplayError;
};

Validate Rows

Note

Data objects must implement IEditableObject to discard changes made to cell values.

Example: How to Cancel Row Modifications at the GridView Level

The Data Grid validates a data row when a user moves focus to another row. This can be useful to identify conflicts between values in different cells in the same data row (for example, a shipping date cannot be earlier than the order date).

Data Grid - Validate Row Demo

The following diagram illustrates how the grid validates data rows:

Data Grid - Validation - Row Diagram

  • ColumnView.ValidateRow / ColumnView.InvalidRowException - Handle these events to validate data rows and respond to invalid values. A user cannot move focus to another row until they correct all errors. The Esc key cancels changes.

    private void gridView1_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e) {
        GridView view = sender as GridView;
        float val = Convert.ToSingle(view.GetRowCellValue(e.RowHandle, gridColumn3)) * 
            Convert.ToInt16(view.GetRowCellValue(e.RowHandle, gridColumn4)) *
            (1 - Convert.ToSingle(view.GetRowCellValue(e.RowHandle, gridColumn5))); //Total Sum
        if(val < 0) {
            e.ErrorText = string.Format("{0}\r\n", Properties.Resources.SubTotalGreaterEqual);
            e.Valid = false;
        }
    }
    
  • ColumnView.SetColumnError - The Data Grid displays a warning message that requires a user to correct or discard the invalid value(s). Use the SetColumnError method to suppress the default notification and display a custom error description and icon in cells with invalid values or in the entire row.

  • Use the ColumnView.UpdateCurrentRow method to force the Grid to validate the focused row.

Run Demo: Validate row on loss of focus

Indicate Invalid Values with IDXDataErrorInfo

Use the DXErrorProvider component and implement the IDXDataErrorInfo interface in a business object to automatically indicate invalid values and display text-based feedback (tooltips).

Indicate Invalid Values with IDXDataErrorInfo - WinForms Data Grid Validation

using DevExpress.XtraGrid.Views.Base;
using DevExpress.XtraEditors.DXErrorProvider;

namespace DXApplication {
    public partial class Form1 : DevExpress.XtraEditors.XtraForm {
        DXErrorProvider errorProvider;
        public Form1() {
            InitializeComponent();
            // Initializes a data source and binds it to the grid control.
            List<MyRecord> records = MyRecord.InitData();
            gridControl1.DataSource = records;
            // Initializes the DXErrorProvider component that handles errors.
            errorProvider = new DXErrorProvider(this);
            // Binds the error provider to the data source to track errors.
            errorProvider.DataSource = records;
        }
    }

    public class MyRecord : IDXDataErrorInfo {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public void GetPropertyError(string propertyName, ErrorInfo info) {
            if(propertyName == "FirstName" && FirstName == "" ||
                propertyName == "LastName" && LastName == "")
                info.ErrorText = string.Format("The {0} field cannot be empty", propertyName);
        }
        public void GetError(ErrorInfo info) { }
        static public List<MyRecord> InitData() {
            return new List<MyRecord>() {
                new MyRecord(){ FirstName = "Mike", LastName = "Brown" },
                new MyRecord(){ FirstName = "Sandra", LastName = "Smith"},
                new MyRecord(){ FirstName = "Andy", LastName = "Muller" }
            };
        }
    }
}

Save User Edits

The Data Grid and other DevExpress data-aware controls (Gantt Control, Vertical Grid, TreeList, etc.) do not interact with real data storages. Instead, they use data sources connected to these storages.

Data-aware controls save user edits to data sources. You should post these changes to underlying storages. Handle the ColumnView.RowUpdated event to post modified row values to the data storage. The Grid raises this event when a user moves focus to another row.

void gridView1_RowUpdated(object sender, RowObjectEventArgs e) {
    // Use data source API to save changes.
}

Handle the ColumnView.CellValueChanged event to save changes each time the user edits a cell.

Note

Ensure that there is no active editor before you save data to a data storage. The BaseView.IsEditing property must return false. Otherwise, call the BaseView.CloseEditor method to close the active editor, and then call the UpdateCurrentRow() method.

void gridView1_CellValueChanged(object sender, CellValueChangedEventArgs e)  {
    ColumnView view = sender as ColumnView;  
    view.CloseEditor();  
    if(view.UpdateCurrentRow()) {  
        // Use data source API to save changes.
    }
}

Read the following topic for detailed information: How to Post Data to Underlying Data Storage.

Tip

If you need to immediately post changes to the data source without moving the focus out of the cell, call the view’s PostEditor() method in the repository item’s EditValueChanged event handler:

repositoryItemCheckedComboBoxEdit1.EditValueChanged += (s, e) => {
    gridControl1.FocusedView.PostEditor();
};

Cheat Sheets and Best Practices

See Also