Cell Values, Editors, and Validation
- 29 minutes to read
Read and Modify Cell Values in Code
Important
These methods should be called 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 | ||
A cell of a focused row | ColumnView.GetFocusedRowCellValue | |
Any row cell | ||
A cell value in an underlying data source | ||
The currently edited cell |
The ColumnView.CellValueChanged event is raised when a user changes a cell value.
The following code samples illustrate this API:
A grid cell editor waits for a user to move focus to another cell or row before its new value is accepted. The code 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;
}
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, and cleared otherwise.
Note
- In Data Grids that display master-detail data sets, detail data is stored in Clone Views, not Pattern Views. To access this data, call the GridView.GetDetailView method to retrieve a Clone View instance, and use its
GetCellValue
orGetRow
methods. See this help topic for more information: Working 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 utilizes the New Item Row to add new rows, the Data Grid initializes new row objects for these rows only after the user modifies a cell.
Cell Editors
Editor Container Architecture: Repository Items and Real Editors
All DevExpress Editors have related repository items. For instance, a RepositoryItemSpinEdit object is a repository item for the SpinEdit editor. Repository items are cores that store a set of properties required to generate an editor. To access an editor’s repository item, use the BaseEdit.Properties property.
All inactive Grid cells contain repository items. When a user clicks a cell to edit its value, the cell’s repository item creates an editor. After a user edits the cell value and deselects this cell (or after you call the CloseEditor/HideEditor methods in code), its editor is destroyed. As a result, an initialized cell editor exists only when the Grid is in edit mode. This technique improves Data Grid performance.
Default Cell Editors
The Data Grid includes support for in-place data editors. To edit a cell value at runtime, a user should focus it and press Enter, or click this cell. The actual behavior depends on the EditorShowMode value. To discard edits, press Esc.
Columns utilize DevExpress Editors to display and edit data source records. Columns automatically choose editors depending on the column data type. For instance, if a column displays dates, it will utilize the DateEdit in-place editor.
Demos: Inplace Cell Editors | Show buttons in grid cells
Replace Default Cell Editors at Design Time
To modify an in-place editor for a Data Grid column, invoke the column’s smart tag menu and use the GridColumn.ColumnEdit property’s drop-down menu to create a new or choose an existing editor.
The Data Grid Designer’s “In-place Editor Repository” page provides centralized access to all in-place editors. In this section, you can add, modify, and remove editors.
Replace Default Cell Editors in Code
To use custom editors for column cells, assign related repository items to the GridColumn.ColumnEdit property. The Assign in-place editors (repository items) demo illustrates how to replace standard checkboxes for the “Mark” column with ToggleSwitch editors.
// Assign a repository item to a column
RepositoryItemToggleSwitch edit = new RepositoryItemToggleSwitch();
gridControl.RepositoryItems.Add(edit);
gridView.Columns["Mark"].ColumnEdit = edit;
If you need to specify an in-place editor for a specific cell rather than an entire column, handle the GridView.CustomRowCellEdit event. Note that any repository item you create in code must be manually added to the grid control’s EditorContainer.RepositoryItems collection.
The code 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;
}
}
The Cell commands to edit and delete rows demo has a “Commands” column with a ButtonEdit cell editor. The editor has two buttons: Edit invokes the Edit Form, Delete removes the current row.
// 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;
}
};
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;
}
};
You can also handle the GridView.CustomRowCellEdit event to replace a default cell editor with an editor of the same type, but with modified settings. This technique is illustrated in the following example: Disable Buttons in Certain Rows.
The code sample below creates two identical [](xref:DevExpress.XtraEditors.Repository.RepositoryItemButtonEdit editors with buttons that copy or remove a cell value. Buttons of one editor are enabled while buttons of the other editor are disabled. The code inside the CustomRowCellEdit event handler assigns the appropriate editor to the “Notes” cells based on whether the adjacent “Mark” cell is checked.
gridView.OptionsView.ShowButtonMode = ShowButtonModeEnum.ShowAlways;
RepositoryItemButtonEdit riButtonEditEnabled = new RepositoryItemButtonEdit();
riButtonEditEnabled.Buttons.Clear();
riButtonEditEnabled.Buttons.Add(new EditorButton(ButtonPredefines.Plus, "Copy cell value"));
riButtonEditEnabled.Buttons.Add(new EditorButton(ButtonPredefines.Delete, "Clear this cell"));
grid.RepositoryItems.Add(riButtonEditEnabled);
RepositoryItemButtonEdit riButtonEditDisabled = new RepositoryItemButtonEdit();
// Create a similar RepositoryItem
riButtonEditDisabled.Assign(riButtonEditEnabled);
// Disable all buttons
riButtonEditDisabled.Buttons.ToList<EditorButton>().ForEach(button => button.Enabled = false);
grid.RepositoryItems.Add(riButtonEditDisabled);
gridView.CustomRowCellEdit += (s, e) => {
if (e.Column.FieldName == "Notes") {
GridView view = s as GridView;
bool actionsAvailable = Convert.ToBoolean(view.GetRowCellValue(e.RowHandle,"Mark"));
e.RepositoryItem = actionsAvailable ? riButtonEditEnabled : riButtonEditDisabled;
}
};
Demos: Assign in-place editors (repository items) | Assign in-place editors dynamically
Use Any Control as a Cell Editor
The RepositoryItemAnyControl allows you to embed any static control into a grid cell. The figure below illustrates an embedded Chart Control.
In order to embed a control, it must implement the DevExpress.XtraEditors.CustomEditor.IAnyControlEdit interface. The Gauge Control implements this interface out of the box. To embed other controls, you need to implement this interface manually.
Embedded Gauge Control: Demo | Example
Embedded Chart Control: Demo | Example
Use Different Controls to Display and Edit Cell Values
Any Data Grid cell uses the same editor to display and edit data. If you require a cell to utilize one editor when a user browses data records, and another editor when a user modifies this cell’s value, handle the GridView.CustomRowCellEditForEditing event.
In the example below, a column with numeric values uses a ProgressBarControl to display cell values. ProgressBar editors do not have UI elements a user can interact with to modify cell values. For a better user experience, when a cell enters Edit mode (users can double-click cells to start editing cell values), the ProgressBar editor is replaced with the SpinEdit editor. Once the editor is back in Display mode (a user presses Enter or focuses another cell), the ProgressBar is visible again.
using DevExpress.XtraEditors.Repository;
// Create separate editors for Display and Edit modes.
RepositoryItem editorForDisplay, editorForEditing;
private void Form1_Load(object sender, EventArgs e) {
// Initialize the editors and assign the default editor to a column.
editorForDisplay = new RepositoryItemProgressBar();
editorForEditing = new RepositoryItemSpinEdit();
gridView1.GridControl.RepositoryItems.AddRange(
new RepositoryItem[] { editorForDisplay, editorForEditing });
gridView1.Columns["Quantity"].ColumnEdit = editorForDisplay;
}
// Assign the editor for in-place editing.
private void gridView1_CustomRowCellEditForEditing(object sender,
CustomRowCellEditEventArgs e) {
if (e.Column.FieldName == "Quantity")
e.RepositoryItem = editorForEditing;
}
Demo: Override the default in-place editor for certain cells
Manage Cell Editors in Code
API | Description |
---|---|
Invokes the focused cell’s editor | |
Closes the currently active editor and discards any changes | |
Saves any changes made and closes the currently active editor | |
Saves any changes made without closing the currently active editor | |
Retrieves the currently active editor | |
Fires whenever an in-place editor activates. The code below automatically sets the current date and opens the DateEdit popup when users activate the “Order Date” column editor.
| |
Fires whenever an in-place editor closes. In the code sample below, focus automatically moves to the cell below after the editor for the current cell closes. This feature allows users to edit each cell within a single column without the need to move focus. This code is not executed when users work with a New Item Row.
|
Edit Data in a Separate Form
Edit Form
Users can use an Edit Form instead of in-place editors to modify grid records. To invoke this form, double-click a grid row at runtime or press the Enter or F2 key.
For regular Views you can select one of three available Edit Form display modes:
- A floating modal form (default mode).
- An in-place form displayed below the grid row that is being edited.
- An in-place form displayed instead of the edited row.
Detail Views do not support in-line edit forms.
Related API
API | Description |
---|---|
Allows you to turn on the Edit Form and select its display mode. | |
Call these methods to manually display and hide an Edit Form. | |
Specifies whether to show confirmation dialogs when users modify records. | |
Gets or sets whether the “Update” and “Cancel” buttons should be displayed. When these buttons are hidden, users can still utilize hotkeys to save (Ctrl+Enter) or discard (Escape) changes. | |
Specifies whether to pass changes to a Data Grid immediately after a user moves focus to another Edit Form field, or only after all changes have been accepted. | |
Allows you to modify a caption of a floating Edit Form. | |
Fires when the Edit Form is about to be shown, and allows you to hide the Edit Form when you do not want users to edit specific cell values. In the Prevent the Edit Form from Showing demo, you cannot edit odd rows.
|
Demos: Inline Edit Form | Prevent the Edit Form from showing | Access an editor within the Edit Form
Modify Values of EditForm Editors and Implement Custom Edit Logic
EditForm is a ContainerControl with editors bound to properties of an underlying data record. To modify values of these editors or implement a custom edit logic, do one of the following:
- Create a custom EditForm and implement the required editor behavior.
- Handle the GridView.EditFormPrepared event to access and customize default EditForm editors.
The following code from the Access an Editor Within the Edit Form demo illustrates how to use the second technique to find the DateEdit editor and focus it.
gridView.OptionsBehavior.EditingMode = GridEditingMode.EditForm;
DateEdit dateEdit = null;
// This event occurs when the EditForm is about to be displayed and allows accessing its editors
gridView.EditFormPrepared += (s, e) => {
// The e.BindableControls collection contains a list of editors located on the EditForm
foreach (Control item in e.BindableControls) {
dateEdit = item as DateEdit;
if (dateEdit != null) {
// Focus the DateEdit editor
dateEdit.Select();
return;
}
}
};
Always remember to remove references to EditForm controls and unsubscribe from event handlers. To do this, handle the EditFormHidden event.
This guideline is applicable to other data-aware controls that support Edit Forms: Gantt Control, Tree List, etc.
Modify Edit Form Layout
The default Edit Form layout is built 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 uses editors utilized by cells in Edit mode.
- An Edit Form’s client area has a table layout with three columns. Each editor (except for MemoEdit and PictureEdit editors) occupies a single cell.
- 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.
To modify this default layout, invoke the Data Grid Designer and switch to its “Edit Form Designer” page. In this page, you can modify layout settings of every column editor.
Related API
API | Description |
---|---|
Provides access to layout settings that affect how an editor for this specific column looks within an Edit Form (see below). | |
Disable this setting to set custom column and row spans for an editor. | |
OptionsColumnEditForm.ColumnSpan | Specify the number of Edit Form columns and/or rows across which an editor stretches. |
OptionsColumnEditForm.Caption | Allow you to modify the editor caption and its relative position. |
OptionsColumnEditForm.Visible | Use these properties to hide and rearange column editors. |
Set this option to true to move the editor to a new row. |
Create Custom Edit Forms
You can create your own User Control and utilize it instead of the default Edit Form.
- Create a User Control and inherit it from the EditFormUserControl class.
- If you have partial classes for this User Control, they must inherit the EditFormUserControl class as well.
- Design your custom User Control UI.
- Use the BoundFieldName and BoundPropertyName extender properties of the parent class to bind editors to data source fields.
- Assign an instance of the custom edit form to the Data Grid GridOptionsEditForm.CustomEditFormLayout property.
- To use this custom form in detail Views, assign separate form instances to each detail View.
using DevExpress.XtraGrid.Views.Grid;
// Custom Edit Form
public class AdvancedEditForm : EditFormUserControl {
public AdvancedEditForm() {
InitializeComponent();
// Bind the EditValue of the textEdit3 editor to the "Price" data field
this.SetBoundFieldName(textEdit3, "Price");
this.SetBoundPropertyName(textEdit3, "EditValue");
}
}
// Use the custom Edit Form in non-master-detail Data Grids
gridView1.OptionsEditForm.CustomEditFormLayout = new AdvancedEditForm();
// Use custom Edit Forms for detail Views
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();
}
Demos: Custom Edit Form | Inline Edit Form
Tip
You can also use a custom form to edit data. See the following KB article for information on how to implement a custom form: Implementing CRUD operations in read-only data sources using XtraGrid.
Manage End-User Input
Use Masks to Limit Data Input
Since DevExpress editors support Masks, you can prevent a user from entering invalid characters. The sample below illustrates how to allow users to enter 10-digit phone numbers with the automatically added “+1” country code.
repositoryItemTextEdit2.Mask.EditMask = "+1 (000) 000-0000";
repositoryItemTextEdit2.Mask.MaskType = DevExpress.XtraEditors.Mask.MaskType.Numeric;
repositoryItemTextEdit1.Mask.UseMaskAsDisplayFormat = true; // Optional
grid.RepositoryItems.Add(repositoryItemTextEdit1);
gridView.Columns["Phone"].ColumnEdit = repositoryItemTextEdit2;
Make Certain Grid Cells Non-Editable
You can prevent users from editing all cell values in a Grid (or column) or specific cell values based on a custom condition.
Global Grid Settings
- Disable a View’s OptionsBehavior.Editable option.
- Enable a column’s OptionsColumn.ReadOnly setting.
- Disable a column’s OptionsColumn.AllowEdit and OptionsColumn.AllowFocus options.
Conditionally Disable In-Place Editing
- Use the Disabled Cell Behavior to disable cells in rows that meet a certain condition. Disabled cells are grayed-out and cannot be edited.
Handle the ColumnView.ShowingEditor event and set its Cancel parameter to true. For instance, the code snippet below prohibits users from editing records whose “Country” field equals “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(); if (cellValue == "Germany") e.Cancel = true; }
You can also check the Read-only mode for certain cells demo where you cannot edit the “ID” column cells for every odd row.
These settings affect only users and do not prevent you from modifying cell values in code.
Conditionally Disable Edit Form Fields
If users utilize an Edit Form to edit cell values, use one of the following techniques to disable the Form’s fields:
Handle the GridView.EditFormPrepared event, and use the
e.BindableControls
collection to access the required editor instance and disable itsBaseEdit.Editable
property.Create a custom Edit Form and specify the editor logic in the custom EditFormUserControl according to your requirements.
Validate Cell Values
Data Grid validates its cell value when a user finishes editing this value and presses Enter or moves focus to another cell within the same row. To forcibly trigger validation, call the BaseView.PostEditor method. The diagram below illustrates this validation process.
BaseView.ValidatingEditor - handle this event to check whether a new cell value is correct and set the Boolean e.Valid parameter accordingly. Users are unable to move focus away from a cell with an incorrect value until the error is fixed or the “Esc” key is pressed to undo changes.
BaseView.InvalidValueException - raises if the e.Valid parameter of the previous event has been set to false and allows you to specify how the Data Grid responds to an invalid value. See the ExceptionMode enumerator values to see the available options.
If the ExceptionMode parameter is set to NoAction, a cell does not accept an invalid value and the Grid does not display any notifications. Use this technique if you want to implement custom notifications. For instance, you can call the ColumnView.SetColumnError method to set default error icons for multiple columns at once.
The code sample below checks the order shipping date, which cannot be earlier than the date this order was placed.
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";
}
}
}
The following code from the Prevent entering duplicate values demo illustrates how to check the “ID” column values and prevent users from entering non-unique 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;
};
The Data Validation demo utilizes a different cell validation approach and employs the GridView.RowCellStyle event to highlight cells with invalid values.
Demos: Data Validation | Validate the active editor’s value | Prevent entering duplicate values
Validate Rows
When the Data Grid validates rows, it does not check cell values until a user moves focus to another row. This can be useful to identify cases where a cell value is technically correct, but conflicts with other cells in the same row. For example, a “Shipping Date” cell stores a valid date, but this date is earlier than its corresponding “Order Date” cell value. To manually trigger row validation, call the ColumnView.UpdateCurrentRow method.
ColumnView.ValidateRow / ColumnView.InvalidRowException events - Similar to per-cell validation, these events allow you to validate new cell values and respond to invalid values. If new cell values do not pass validation, users are kept on the current row to either correct all errors, or press Esc and undo the changes. Note that to revert row cell values back to correct values, data source objects must implement the IEditableObject interface.
ColumnView.SetColumnError method - If a row is invalid, the Data Grid displays a message that requires a user to either correct or discard the invalid values. To suppress this default notification, call the ColumnView.SetColumnError method to mark specific cells (or the entire row) as invalid manually.
In the Data Validation demo, the ValidateRow event is handled to calculate values of the “Sub Total” column cells based on the “Unit Price”, “Quantity” and “Discount” column cells. Negative subtotal values are not accepted.
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;
}
}
Demos: Data Validation | Validate row data on losing focus
Save User Edits
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, but you need to manually post these changes to underlying storages. See this help topic for more information: Post Data to an Underlying Data Source.
To post modified row values to an underlying source, handle the ColumnView.RowUpdated event. This event fires when a user navigates away from the edited row.
void gridView1_RowUpdated(object sender, RowObjectEventArgs e) {
//use data source API to save changes
}
If you want to save changes every time a user edits a cell, handle the ColumnView.CellValueChanged event instead.
Note that before you save data to a storage, you need to ensure there is no active editor (the BaseView.IsEditing property returns false). Call the BaseView.CloseEditor method to close the active editor, and then call the BaseView.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
}
}