Editing With Edit Form

The Grid View control provides end-user data editing functionality out of the box. The commands for end-user data modification are displayed within a command column. Add this column to the grid’s Columns to allow editing.

By default, a built-in Edit Form is used to modify cell values. The Edit Form displays edit cells that correspond to data columns, and the Cancel/Update commands that allow end-users to discard changes or save them to a database.

By default all data editing operations are prohibited. In this demo, row insertion, deletion, and editing is explicitly enabled using settings available through the SettingDataSecurity property.

First Name Last Name Title Birth Date City Country
NancyDavolioSales Representative12/8/1978SeattleUSA
 AndrewFullerVice President, Sales2/19/1965TacomaUSA
JanetLeverlingSales Representative8/30/1985KirklandUSA
MargaretPeacockSales Representative9/19/1973RedmondUSA
StevenBuchananSales Manager3/4/1955LondonUK
MichaelSuyamaSales Representative7/2/1981LondonUK
RobertKingSales Representative5/29/1960LondonUK
LauraCallahanInside Sales Coordinator1/9/1985SeattleUSA
AnneDodsworthSales Representative1/27/1980LondonUK
<dx:BootstrapGridView runat="server" DataSourceID="DataSourceEditingEditForm" KeyFieldName="EmployeeID" EnableRowsCache="False">
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowEditButton="true" ShowDeleteButton="true" ShowNewButtonInHeader="true" />
        <dx:BootstrapGridViewDataColumn FieldName="FirstName" />
        <dx:BootstrapGridViewDataColumn FieldName="LastName" />
        <dx:BootstrapGridViewDataColumn FieldName="Title" />
        <dx:BootstrapGridViewDateColumn FieldName="BirthDate" />
        <dx:BootstrapGridViewDataColumn FieldName="City" />
        <dx:BootstrapGridViewDataColumn FieldName="Country" />
    </Columns>
</dx:BootstrapGridView>

Batch Editing and Updating

The Grid View control allows you to edit and update multiple grid rows on the client side and send them to the server in a single request.

To enable batch editing, set the SettingsEditing.Mode property to 'Batch'. In this mode, you can use in-line editors to edit grid data (the modified cells are highlighted). Deleted rows are also highlighted and display the Recover command item. To hide the deleted rows, set the SettingsEditing.BatchEditSettings.HighlightDeletedRows property to false. All changes are maintained on the client side until the Save changes link is clicked, or the Cancel changes button is clicked to cancel all the changes.

If a grid contains modified data, it displays a confirmation message before a postback or callback. When the grid supports callbacks, you can manage changed rows that belong to different pages. You can use the Preview changes button to preview and modify inserted, deleted and edited rows before you click Update.

You can use the following properties to customize the batch edit mode settings:

  • The KeepChangesOnCallbacks property specifies whether the grid keeps changes made in batch edit mode on callbacks.
  • The EditMode property allows you to specify which control element (data cell or data row) is used to edit data.
  • The StartEditAction property specifies the action that is used to edit grid data.

The batchEditApi property provides access to the batch edit client API. The BatchEditStartEditing and BatchEditEndEditing events occur when a grid switches to/leaves the batch edit mode.

All data editing operations are prohibited. In this demo, the SettingDataSecurity property’s settings are used to unable row insertion, deletion, and editing.

First Name Last Name Title Birth Date City Country
NancyDavolioSales Representative12/8/1978SeattleUSA
AndrewFullerVice President, Sales2/19/1965TacomaUSA
JanetLeverlingSales Representative8/30/1985KirklandUSA
MargaretPeacockSales Representative9/19/1973RedmondUSA
StevenBuchananSales Manager3/4/1955LondonUK
MichaelSuyamaSales Representative7/2/1981LondonUK
RobertKingSales Representative5/29/1960LondonUK
LauraCallahanInside Sales Coordinator1/9/1985SeattleUSA
AnneDodsworthSales Representative1/27/1980LondonUK
Inserted values
Updated values
Deleted values
<dx:BootstrapGridView runat="server" DataSourceID="DataSourceBatchEditing" KeyFieldName="EmployeeID" EnableRowsCache="False">
    <SettingsEditing Mode="Batch"></SettingsEditing>
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowCancelButton="true" ShowDeleteButton="true" ShowNewButtonInHeader="true" Width="80px" />
        <dx:BootstrapGridViewDataColumn FieldName="FirstName" />
        <dx:BootstrapGridViewDataColumn FieldName="LastName" />
        <dx:BootstrapGridViewDataColumn FieldName="Title" />
        <dx:BootstrapGridViewDateColumn FieldName="BirthDate" />
        <dx:BootstrapGridViewDataColumn FieldName="City" />
        <dx:BootstrapGridViewDataColumn FieldName="Country" />
    </Columns>
</dx:BootstrapGridView>

Editing in Popup Edit Form

In this mode, the Edit Form is displayed within a popup window. To use this mode, set the SettingsEditing.Mode property to PopupEditForm.

By default, all data editing operations are prohibited. In this demo, row insertion, deletion, and editing is explicitly enabled using settings available through the SettingDataSecurity property.

First Name Last Name Title Birth Date City Country
NancyDavolioSales Representative12/8/1978SeattleUSA
AndrewFullerVice President, Sales2/19/1965TacomaUSA
JanetLeverlingSales Representative8/30/1985KirklandUSA
MargaretPeacockSales Representative9/19/1973RedmondUSA
StevenBuchananSales Manager3/4/1955LondonUK
MichaelSuyamaSales Representative7/2/1981LondonUK
RobertKingSales Representative5/29/1960LondonUK
LauraCallahanInside Sales Coordinator1/9/1985SeattleUSA
AnneDodsworthSales Representative1/27/1980LondonUK
<dx:BootstrapGridView runat="server" DataSourceID="DataSourceEditingPopupEditForm" KeyFieldName="EmployeeID" EnableRowsCache="False">
    <SettingsEditing Mode="PopupEditForm"></SettingsEditing>
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowEditButton="true" ShowDeleteButton="true" ShowNewButtonInHeader="true" />
        <dx:BootstrapGridViewDataColumn FieldName="FirstName" />
        <dx:BootstrapGridViewDataColumn FieldName="LastName" />
        <dx:BootstrapGridViewDataColumn FieldName="Title" />
        <dx:BootstrapGridViewDateColumn FieldName="BirthDate" />
        <dx:BootstrapGridViewDataColumn FieldName="City" />
        <dx:BootstrapGridViewDataColumn FieldName="Country" />
    </Columns>
</dx:BootstrapGridView>

Inline Editing

In the inline editing mode, the Grid View control displays an In-Line Edit Row instead of the edited data row. The edit row displays edit cells that correspond to visible data columns. To use this mode, set the SettingsEditing.Mode property to Inline.

By default, all data editing operations are prohibited. In this demo, row insertion, deletion, and editing is explicitly enabled using settings available through the SettingDataSecurity property.

First Name Last Name Title Birth Date Country
NancyDavolioSales Representative12/8/1978USA
JanetLeverlingSales Representative8/30/1985USA
MargaretPeacockSales Representative9/19/1973USA
StevenBuchananSales Manager3/4/1955UK
MichaelSuyamaSales Representative7/2/1981UK
RobertKingSales Representative5/29/1960UK
LauraCallahanInside Sales Coordinator1/9/1985USA
AnneDodsworthSales Representative1/27/1980UK
<dx:BootstrapGridView runat="server" DataSourceID="DataSourceInlineEditing" KeyFieldName="EmployeeID" EnableRowsCache="False">
    <SettingsEditing Mode="Inline"></SettingsEditing>
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowEditButton="true" ShowDeleteButton="true" ShowNewButtonInHeader="true" Width="150px" />
        <dx:BootstrapGridViewDataColumn FieldName="FirstName" />
        <dx:BootstrapGridViewDataColumn FieldName="LastName" />
        <dx:BootstrapGridViewDataColumn FieldName="Title" />
        <dx:BootstrapGridViewDateColumn FieldName="BirthDate" />
        <dx:BootstrapGridViewDataColumn FieldName="Country" />
    </Columns>
</dx:BootstrapGridView>

Cascading ComboBoxes

In this demo, the combo box in the City column (the City combo box) is populated dynamically with city names using callbacks, based on the value selected in the combo box in the Country column (the Country combo box). Only the content stored in the City combo box is updated during round-trips to the server - not the content of the page or the Grid View control.

The client-side SelectedIndexChanged event of the Country combo box is handled to update the City combo box. On the server side, the Callback event is handled to populate the City combo box with required values.

By default, all data editing operations are prohibited. In this demo, row insertion, deletion, and editing is explicitly enabled using settings available through the SettingDataSecurity property.

#Country City Contact Name Company Name
GermanyBerlinMaria AndersAlfreds Futterkiste
MexicoMéxico D.F.Ana TrujilloAna Trujillo Emparedados y helados
MexicoMéxico D.F.Antonio MorenoAntonio Moreno Taquería
SwedenLuleåChristina BerglundBerglunds snabbköp
GermanyMannheimHanna MoosBlauer See Delikatessen
FranceStrasbourgFrédérique CiteauxBlondesddsl père et fils
SpainMadridMartín SommerBólido Comidas preparadas
FranceMarseilleLaurence LebihanBon app'
CanadaTsawassenElizabeth LincolnBottom-Dollar Markets
<dx:BootstrapGridView ClientInstanceName="grid" runat="server" DataSourceID="DataSourceCascadingComboBoxes"
    KeyFieldName="CustomerID" OnCellEditorInitialize="grid_CellEditorInitialize">
    <SettingsEditing Mode="Inline" />
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowEditButton="true" />
        <dx:BootstrapGridViewComboBoxColumn FieldName="Country">
            <PropertiesComboBox DataSourceID="CountriesDataSource" TextField="CountryName"
                ValueField="CountryName" EnableSynchronization="False" IncrementalFilteringMode="StartsWith">
                <ClientSideEvents SelectedIndexChanged="onCountryChanged"></ClientSideEvents>
            </PropertiesComboBox>
        </dx:BootstrapGridViewComboBoxColumn>
        <dx:BootstrapGridViewComboBoxColumn FieldName="City">
            <PropertiesComboBox EnableSynchronization="False" IncrementalFilteringMode="StartsWith"></PropertiesComboBox>
        </dx:BootstrapGridViewComboBoxColumn>
        <dx:BootstrapGridViewDataColumn FieldName="ContactName">
        </dx:BootstrapGridViewDataColumn>
        <dx:BootstrapGridViewDataColumn FieldName="CompanyName">
        </dx:BootstrapGridViewDataColumn>
    </Columns>
</dx:BootstrapGridView>
protected void grid_CellEditorInitialize(object sender, BootstrapGridViewEditorEventArgs e) {
    BootstrapGridView grid = (BootstrapGridView)sender;
    if(!grid.IsEditing || e.Column.FieldName != "City" || e.KeyValue == DBNull.Value || e.KeyValue == null)
        return;
    string country = (string)grid.GetRowValuesByKeyValue(e.KeyValue, "Country");
    BootstrapComboBox cmbCity = (BootstrapComboBox)e.Editor;
    FillCityComboBox(cmbCity, country);
    cmbCity.Callback += cmbCity_OnCallback;
}
protected void FillCityComboBox(BootstrapComboBox cmbCity, string country) {
    cmbCity.Items.Clear();
    foreach(string city in GetCities(country))
        cmbCity.Items.Add(city);
}
List<string> GetCities(string country) {
    using(var context = new DevExpress.Web.Demos.WorldCitiesContextSL())
        return context.Cities.Where(c => c.Country.CountryName == country).OrderBy(c => c.CityName).Select(c => c.CityName).ToList();
}
void cmbCity_OnCallback(object source, CallbackEventArgsBase e) {
    FillCityComboBox((BootstrapComboBox)source, e.Parameter);
}
function onCountryChanged(cmbCountry) {
    var cmbCity = grid.GetEditor("City");
    cmbCountry.SetEnabled(false);
    cmbCity.PerformCallback(cmbCountry.GetValue().toString(), function() {
        cmbCountry.SetEnabled(true);
        cmbCity.SetSelectedIndex(0);
    });
}

Data Validation

The Grid View Control allows you to manually validate the edited row and display errors for invalid fields. This demo demonstrates how you can provide data validation by handling the RowValidating event.

To indicate rows with invalid data, the HtmlRowPrepared event is handled. This event is raised for each data row when the corresponding row within the table has been created. In this sample, rows with invalid data are colored in red (a text-danger CSS class is applied).

In the Edit Form, an error icon indicates an invalid field. Hover over the icon with the mouse to display a hint along with a description of the error.

By default, all data editing operations are prohibited. In this demo, row insertion, deletion, and editing is explicitly enabled using settings available through the SettingDataSecurity property.

# Age Email Arrival Date
  Andrew Fuller 42andrew.fuller@devexpress.com9/16/2019
Please, correct all errors.
Margaret Peackop 48margaret.peackop.devexpress.com10/24/2019
Nancy Davolio 34nancy.davolio@devexpress.com10/22/2019
Robert King 29robert.king@devexpress.com10/23/2019
Anne Dodsworth 17anne.dodsworth@devexpress.com10/22/2019
<dx:BootstrapGridView ID="GridViewDataValidation" runat="server" DataSourceID="PersonsDataSource" KeyFieldName="Id" EnableRowsCache="False"
    OnHtmlRowPrepared="grid_HtmlRowPrepared" OnRowValidating="grid_RowValidating" OnStartRowEditing="grid_StartRowEditing">
    <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
    <Columns>
        <dx:BootstrapGridViewCommandColumn ShowEditButton="true" />
        <dx:BootstrapGridViewDataColumn>
            <SettingsEditForm Visible="False" />
            <DataItemTemplate>
                <%# Eval("FirstName") %> <%# Eval("LastName") %>
            </DataItemTemplate>
        </dx:BootstrapGridViewDataColumn>
        <dx:BootstrapGridViewTextColumn FieldName="Age">
            <PropertiesTextEdit>
                <ValidationSettings RequiredField-IsRequired="true"></ValidationSettings>
            </PropertiesTextEdit>
        </dx:BootstrapGridViewTextColumn>
        <dx:BootstrapGridViewTextColumn FieldName="Email">
            <PropertiesTextEdit>
                <ValidationSettings RequiredField-IsRequired="true"></ValidationSettings>
            </PropertiesTextEdit>
        </dx:BootstrapGridViewTextColumn>
        <dx:BootstrapGridViewDateColumn FieldName="ArrivalDate">
            <PropertiesDateEdit>
                <ValidationSettings RequiredField-IsRequired="true"></ValidationSettings>
            </PropertiesDateEdit>
        </dx:BootstrapGridViewDateColumn>
    </Columns>
</dx:BootstrapGridView>
protected void grid_RowValidating(object sender, DevExpress.Web.Data.ASPxDataValidationEventArgs e) {
    var errors = ValidateRow((string)e.NewValues["Email"], (int)e.NewValues["Age"], (DateTime)e.NewValues["ArrivalDate"]);
    if(string.IsNullOrEmpty(e.RowError) && errors.Any())
        e.RowError = "Please, correct all errors.";
    foreach(var key in errors.Keys)
        e.Errors[GridViewDataValidation.Columns[key]] = errors[key];
}
protected void grid_HtmlRowPrepared(object sender, ASPxGridViewTableRowEventArgs e) {
    if(!object.Equals(e.RowType, GridViewRowType.Data)) return;
    var errors = ValidateRow((string)e.GetValue("Email"), (int)e.GetValue("Age"), (DateTime)e.GetValue("ArrivalDate"));
    if(errors.Any())
        e.Row.CssClass = "text-danger";
}
protected void grid_StartRowEditing(object sender, DevExpress.Web.Data.ASPxStartRowEditingEventArgs e) {
    if(!GridViewDataValidation.IsNewRowEditing)
        GridViewDataValidation.DoRowValidation();
}
protected Dictionary<string, string> ValidateRow(string email, int age, DateTime arrival) {
    var errors = new Dictionary<string, string>();
    if(!email.Contains("@"))
        errors["Email"] = "Invalid e-mail.";
    if(age < 18)
        errors["Age"] = "Age must be greater than or equal 18.";
    if(DateTime.Today.Year != arrival.Year || DateTime.Today.Month != arrival.Month)
        errors["ArrivalDate"] = "Arrival date is required and must belong to the current month.";
    return errors;
}

Editing with Floating Action Button

The DevExpress Bootstrap Floating Action Button is a button that appears in front of a container (HTML element or control) when users interact with the container's elements.

The following types of floating action buttons are available:

  • Action - Executes the action once users click the floating action button.
  • Action Group - The floating action button serves as a container for multiple actions (action items). When pressed, the floating action button expands nested actions.

This demo adds an floating action button to a grid control. The type of the button depends on the context. For instance, when an end-user clicks a grid row, the button becames the action group with two popup actions - Edit and Delete. The JS code-behind file handles the button clicks and switches contexts.

First Name Last Name Title Birth Date City Country
NancyDavolioSales Representative12/8/1978SeattleUSA
AndrewFullerVice President, Sales2/19/1965TacomaUSA
JanetLeverlingSales Representative8/30/1985KirklandUSA
MargaretPeacockSales Representative9/19/1973RedmondUSA
StevenBuchananSales Manager3/4/1955LondonUK
MichaelSuyamaSales Representative7/2/1981LondonUK
RobertKingSales Representative5/29/1960LondonUK
LauraCallahanInside Sales Coordinator1/9/1985SeattleUSA
AnneDodsworthSales Representative1/27/1980LondonUK
<dx:BootstrapFloatingActionButton ClientInstanceName="fab" runat="server"
    ContainerCssSelector="#container" InitialActionContext="NewRowContext">
    <Items>
        <dx:BootstrapFABAction ActionName="NewRow" ContextName="NewRowContext" Text="Add new row"></dx:BootstrapFABAction>
        <dx:BootstrapFABAction ActionName="Cancel" ContextName="CancelContext" IconCssClass="dxbs-icon dxbs-icon-fab-collapse"></dx:BootstrapFABAction>
        <dx:BootstrapFABActionGroup ContextName="FocusedRowContext">
            <Items>
                <dx:BootstrapFABActionItem ActionName="DeleteRow" IconCssClass="icon icon-Delete"></dx:BootstrapFABActionItem>
                <dx:BootstrapFABActionItem ActionName="EditRow" IconCssClass="icon icon-Edit"></dx:BootstrapFABActionItem>
            </Items>
        </dx:BootstrapFABActionGroup>
        <dx:BootstrapFABActionGroup ContextName="EditingRowContext" Text="Cancel" CollapseIconCssClass="dxbs-icon dxbs-icon-fab-collapse">
            <Items>
                <dx:BootstrapFABActionItem ActionName="Save" IconCssClass="icon icon-Save"></dx:BootstrapFABActionItem>
            </Items>
        </dx:BootstrapFABActionGroup>
    </Items>
    <ClientSideEvents
        ActionItemClick="OnActionItemClick"
        ActionCollapsing="OnActionCollapsing"
    />
</dx:BootstrapFloatingActionButton>
<div id="container">
    <dx:BootstrapGridView runat="server" DataSourceID="DataSourceEditingWithFAB" KeyFieldName="EmployeeID"
        EnableRowsCache="False" ClientInstanceName="gridFAB" OnCommandButtonInitialize="GridViewDataValidation_CommandButtonInitialize">
        <ClientSideEvents
            Init="OnGridViewInit"
            RowClick="OnRowClick"
            EndCallback="OnEndCallback"
        />
        <SettingsDataSecurity AllowEdit="true" AllowDelete="true" AllowInsert="true" />
        <SettingsBehavior AllowFocusedRow="true" />
        <Columns>
            <dx:BootstrapGridViewDataColumn FieldName="FirstName" />
            <dx:BootstrapGridViewDataColumn FieldName="LastName" />
            <dx:BootstrapGridViewDataColumn FieldName="Title" />
            <dx:BootstrapGridViewDateColumn FieldName="BirthDate" />
            <dx:BootstrapGridViewDataColumn FieldName="City" />
            <dx:BootstrapGridViewDataColumn FieldName="Country" />
        </Columns>
    </dx:BootstrapGridView>
</div>
function OnActionItemClick(s, e) {
    if(e.actionName === "NewRow") {
        gridFAB.AddNewRow();
    }
    else if(e.actionName === "EditRow") {
        gridFAB.StartEditRow(gridFAB.GetFocusedRowIndex());
        gridFAB.SetFocusedRowIndex(-1);
    }
    else if(e.actionName === "DeleteRow") {
        gridFAB.DeleteRow(gridFAB.GetFocusedRowIndex());
        gridFAB.SetFocusedRowIndex(-1);
    }
    else if(e.actionName === "Save") {
        gridFAB.UpdateEdit();
    }
    else if(e.actionName === "Cancel") {
        gridFAB.CancelEdit();
    }
}
function OnActionCollapsing(s, e) {
    if((e.contextName === "FocusedRowContext" || e.contextName === "EditingRowContext") && e.collapseReason === ASPxClientFloatingActionButtonCollapseReason.CollapseButton) {
        setTimeout(function () {
            gridFAB.CancelEdit();
            gridFAB.SetFocusedRowIndex(-1);
            fab.SetActionContext("NewRowContext");
        }, 100);
    }
}
function OnGridViewInit(s, e) {
    fab.SetActionContext("NewRowContext");
    s.SetFocusedRowIndex(-1);
}
function OnRowClick(s, e) {
    if(s.IsNewRowEditing() || s.IsEditing())
        e.cancel = true;
    else
        fab.SetActionContext("FocusedRowContext", true);
}
function OnEndCallback(s, e) {
    if(s.IsNewRowEditing() || s.IsEditing()) {
        fab.SetActionContext("CancelContext", true);
        ASPxClientEdit.AttachEditorModificationListener(onEditorsChanged, function (control) {
            var parent = control.GetParentControl();
            if(parent && parent instanceof dx.BootstrapClientFormLayout)
                return parent.GetParentControl() === gridFAB
            else
                return false;
        });
    }
    else {
        fab.SetActionContext("NewRowContext");
        s.SetFocusedRowIndex(-1);
    }
}
function onEditorsChanged(s, e) {
    fab.SetActionContext("EditingRowContext", true);
}
Screen Size
Color Themes
Demo QR Code