- DataGridView Overview
- Basic Data Binding with the DataGridView
- Controlling Modifications to Data in the Grid
- Programmatic DataGridView Construction
- Custom Column Content with Unbound Columns
- Displaying Computed Data in Virtual Mode
- Using the Built-In Column Types
- Built-In Header Cells
- Handling Grid Data Edits
- Automatic Column Sizing
- Column and Row Freezing
- Using the Designer to Define Grids
- Column Reordering
- Defining Custom Column and Cell Types
- Utilizing Cell-Oriented Grid Features
- Formatting with Styles
- Where Are We?
Handling Grid Data Edits
How you handle grid edits is going to depend on the following:
- The type of column or cell you are dealing with
- Whether the data is data bound
- Whether you are in virtual mode
As mentioned earlier, when working with a text box column, users can start editing a cell by putting the focus into the cell with the mouse, arrow keys, or by pressing the F2 key when the mouse pointer is in the cell. If users then start typing characters, the current contents of the cell will be overwritten. When they change the focus to another cell, this completes the editing process.
The first thing that happens that you might want to handle is that the CellParsing event fires. Like its CellFormatting counterpart, this event gives you an opportunity to intercept the value that was entered into the cell while in edit mode, either to handle storing that value somewhere yourself or to transform it into some other value before it is stored.
If the cell is data bound, and if the data source supports editing the data objects in the collection, the data will automatically be pushed back into the underlying data source. If the cell is a button or link cell, however, you won’t be able to edit the contents in the first place because they don’t support editing. If the cell is a combo box cell, editing is done by selecting a value in the drop-down list or overtyping the current selection if the cell has its DisplayStyle property set to ComboBox. This changes the cell’s value when editing is complete (when the focus moves off the cell) and results in the same action as if that value had been typed into a text box cell. If the grid is in virtual mode, you will need to handle the CellValuePushed event to grab the value that was entered and do what you need to with it.
When a cell switches into edit mode, an event named EditingControlShowing fires. This event passes an event argument that lets you get a reference to the editing control itself. The built-in cell types that support editing (text box, combo box, and check box cell types) create an instance of an editing control that derives from their normal Windows Forms counterparts (TextBox, ComboBox, and CheckBox, respectively) and display that control as a child control inside a panel inside the cell. If you create a custom cell type that supports editing, then you will want to follow a similar approach. Through the EditingControlShowing event, you can get a reference to the editing control in use and can tap into its event model to respond to edits in realtime. For example, if you want to dynamically react to selections in a combo box column while the control is still in edit mode and the selected value hasn’t been pushed yet into the cell’s underlying value (meaning the CellParsing event hasn’t yet fired), you could use the EditingControlShowing event to hook things up:
public Form1() { InitializeComponent(); m_Grid.EditingControlShowing += OnEditControlShowing(); } private void OnEditControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e) { if (m_Grid.CurrentCell.ColumnIndex == 2) { m_HookedCombo = e.Control as ComboBox; if (m_HookedCombo == null) return; m_HookedCombo.SelectedIndexChanged += OnCountryComboChanged; } } void OnCountryComboChanged(object sender, EventArgs e) { string countryName = (string)m_Grid.CurrentCell.EditedFormattedValue; if (string.IsNullOrEmpty(countryName)) return; DataRow[] countries = m_MoneyData.Countries.Select( string.Format("CountryName = '{0}'", countryName)); if (countries != null && countries.Length > 0) { MoneyDBDataSet.CountriesRow row = countries[0] as MoneyDBDataSet.CountriesRow; int flagColIndex = m_Grid.Columns["TargetCountryFlag"].Index; DataGridViewCell cell = m_Grid.CurrentRow.Cells[flagColIndex]; cell.Value = row.Flag; } }
This code does the following:
- The constructor subscribes the OnEditControlShowing method to the grid’s EditControlShowing event.
- When the EditControlShowing event fires, the OnEditControlShowing method uses the Control property on the event argument to get a reference to the ComboBox control that is embedded in the cell that is being edited.
- The OnEditControlShowing method then subscribes the OnCountryComboChanged method to the SelectedIndexChanged event on that ComboBox control.
- When the SelectedIndexChanged event fires, the OnCountryComboChanged method retrieves the country name from the cell containing the drop-down list using the current cell’s EditedFormattedValue property. This lets you get the edited value before the cell has left editing mode.
- The OnCountryComboChanged method then uses the country name to retrieve the corresponding row in the Countries table and extracts the flag image from the Flag column.
- Finally, it sets the flag image as the value on the cell corresponding to the country’s flag.
Keep in mind that the Flag column in the Countries table is actually a byte array containing the bits of the saved image file. The automatic formatting of the image column kicks in here to present the image in the same way that was discussed for a PictureBox control in Chapter 4. The ColumnTypes sample in the download code demonstrates this technique.