DataGridView Control

The DataGridView control is the new grid control for Windows Froms 2.0. It replaces the DataGrid control with an easy to use and extremely customizable grid that supports many of the features that are needed for our customers.

About this document:

This material should not be considered a complete coverage of DataGridView but it tries to capture the high-level features with some depth in specific areas.

This document is divided into about 5 logical sections starting with a feature and structure overview, followed by an overview of built‑in column and cell types. Next is an overview of working with data, followed by an overview of specific major features. Lastly, a “best practice” section concludes the main part of this document.

Most sections contain a “Q & A” section that answers common questions regarding the specific feature or area covered by the section. Note that some questions are duplicated in multiple sections based upon the section relevancy. The question and answers with code samples/snippets are contained in this document’s only appendix to make for a “one-stop shop” of code.

Note that most of the context of this document comes from the DataGridView control documentation presented in MSDN.

Contents

1      What is the DataGridView.. 4

1.1    Differences between the DataGridView and DataGrid controls. 4

1.2    Highlight of features. 5

2      Structure of DGV.. 6

2.1    Architecture Elements. 6

2.2    Cells and Bands. 6

2.3    DataGridViewCell 6

2.3.1      How a DataGridViewCell works. 7

2.4    DataGridViewColumn. 9

2.5    DataGridView Editing Controls. 9

2.6    DataGridViewRow.. 10

3      Out of the box column/cell types. 11

3.1    DataGridViewTextBoxColumn. 11

3.2    DataGridViewCheckBoxColumn. 12

3.3    DataGridViewImageColumn. 12

3.4    DataGridViewButtonColumn. 13

3.5    DataGridViewComboBoxColumn. 13

3.5.1      DataErrors and the combo box column. 13

3.6    DataGridViewLinkColumn. 14

4      Working with Data. 15

4.1    Data Entry and Validation Events. 15

4.1.1      Order of Validation Events. 15

4.1.2      Validating Data. 15

4.1.3      Data Entry in the New Row.. 16

4.2    Working with Null values. 19

4.2.1      NullValue. 19

4.2.2      DataSourceNullValue. 19

4.3    DataError event 20

4.4    Databound modes. 21

4.4.1      Unbound. 21

4.4.2      Bound. 21

4.4.3      Virtual 22

4.4.4      Mixed mode – Bound and Unbound. 22

5      Overview of features. 24

5.1    Styling. 24

5.1.1      The DataGridViewCellStyle Class. 24

5.1.2      Using DataGridViewCellStyle Objects. 24

5.1.3      Style Inheritance. 25

5.1.4      Setting Styles Dynamically. 28

5.2    Custom painting. 28

5.2.1      Paint Parts. 28

5.2.2      Row Pre Paint and Post Paint 29

5.3    Autosizing. 30

5.3.1      Sizing Options in the Windows Forms DataGridView Control 30

5.3.2      Resizing with the Mouse. 31

5.3.3      Automatic Sizing. 32

5.3.4      Programmatic Resizing. 33

5.3.5      Customizing Content-based Sizing Behavior. 34

5.3.6      Content-based Sizing Options. 34

5.4    Selection modes. 34

5.4.1      Programmatic Selection. 35

5.5    Scrolling. 35

5.5.1      Scroll event 35

5.5.2      Scroll bars. 35

5.5.3      Scrolling Properties. 36

5.6    Sorting. 36

5.6.1      Programmatic Sorting. 37

5.6.2      Custom Sorting. 38

5.7    Border styles. 39

5.7.1      Standard Border Styles. 39

5.7.2      Advanced Border Styles. 39

5.8    Enter-Edit modes. 40

5.9    Clipboard copy modes. 40

5.10  Frozen columns/rows. 41

5.11  Implementing Custom cells and editing controls/cells. 41

5.11.1    IDataGridViewEditingControl 42

5.11.2    IDataGridViewEditingCell 42

5.12  Virtual mode. 42

5.12.1    Bound Mode and Virtual Mode. 42

5.12.2    Supplementing Bound Mode. 42

5.12.3    Replacing Bound Mode. 43

5.12.4    Virtual-Mode Events. 43

5.12.5    Best Practices in Virtual Mode. 44

5.13  Capacity. 44

6      Best Practices. 45

6.1    Using Cell Styles Efficiently. 45

6.2    Using Shortcut Menus Efficiently. 45

6.3    Using Automatic Resizing Efficiently. 45

6.4    Using the Selected Cells, Rows, and Columns Collections Efficiently. 46

6.5    Using Shared Rows. 46

6.6    Preventing Rows from Becoming Unshared. 47

Appendix A – Common Questions and Answers. 49

1.      How do I prevent a particular cell from being editable?. 49

2.      How do I disable a cell?. 49

3.      How do I restrict user from setting focus to a specific cell?. 51

4.      How do I show controls in all cells regardless of edit?. 51

5.      Why does the cell text show up with “square” characters where they should be new lines?. 51

6.      How do I show icon and text in the same cell?. 51

7.      How do I hide a column?. 53

8.      How do I prevent the user from sorting on a column?. 53

9.      How do I sort on multiple columns?. 54

10.    How do I hook up events on the editing control?. 58

11.    When should I remove event handlers from the editing control?. 58

12.    How do I handle the SelectedIndexChanged event?. 58

13.    How do I perform drag and drop reorder of rows?. 59

14.    How do I make the last column wide enough to occupy all the remaining client area of the grid?. 60

15.    How do I have the cell text wrap?. 60

16.    How do I make the image column not show any images?. 61

17.    How do I enable typing in the combo box cell?. 61

18.    How do I have a combo box column display a sub set of data based upon the value of a different combo box column?  61

19.    How do I show the error icon when the user is editing the cell?. 62

20.    How do I show unbound data along with bound data?. 65

21.    How do I show data that comes from two tables?. 66

22.    How do I show master-details?. 66

23.    How do I show master-details in the same DataGridView?. 68

24.    How do I prevent sorting?. 68

25.    How do I commit the data to the database when clicking on a toolstrip button?. 68

26.    How do I display a confirmation dialog when the user tries to delete a row?. 68

1                  What is the DataGridView

With the DataGridView control, you can display and edit tabular data from many different kinds of data sources.

The DataGridView control is highly configurable and extensible, and it provides many properties, methods, and events to customize its appearance and behavior. When you want your Windows Forms application to display tabular data, consider using the DataGridView control before others (for example, DataGrid). If you are displaying a small grid of read-only values, or if you are enabling a user to edit a table with millions of records, the DataGridView control will provide you with a readily programmable, memory-efficient solution.

The DataGridView control replaces and adds functionality to the DataGrid control; however, the DataGrid control is retained for both backward compatibility and future use, if you choose. See below for details on the differences between the DataGrid and DataGridView controls.

1.1           Differences between the DataGridView and DataGrid controls

The DataGridView control provides numerous basic and advanced features that are missing in the DataGrid control. Additionally, the architecture of the DataGridView control makes it much easier to extend and customize than the DataGrid control.

The following table describes a few of the primary features available in the DataGridView control that are missing from the DataGrid control.

DataGridView control feature

Description

Multiple column types

The DataGridView control provides more built-in column types than the DataGrid control. These column types meet the needs of most common scenarios, but are also easier to extend or replace than the column types in the DataGrid control.

Multiple ways to display data

The DataGrid control is limited to displaying data from an external data source. The DataGridView control, however, can display unbound data stored in the control, data from a bound data source, or bound and unbound data together. You can also implement virtual mode in the DataGridView control to provide custom data management.

Multiple ways to customize the display of data

The DataGridView control provides many properties and events that enable you to specify how data is formatted and displayed. For example, you can change the appearance of cells, rows, and columns depending on the data they contain, or you can replace data of one data type with equivalent data of another type.

Multiple options for changing cell, row, column, and header appearance and behavior

The DataGridView control enables you to work with individual grid components in numerous ways. For example, you can freeze rows and columns to prevent them from scrolling; hide rows, columns, and headers; change the way row, column, and header sizes are adjusted; change the way users make selections; and provide ToolTips and shortcut menus for individual cells, rows, and columns.

The only feature that is available in the DataGrid control that is not available in the DataGridView control is the hierarchical display of information from two related tables in a single control. You must use two DataGridView controls to display information from two tables that are in a master/detail relationship.

1.2           Highlight of features

The following table highlights the DataGridView’s major features. Further details about a feature can be found later in this document

DataGridView control feature

Description

Multiple column types

The DataGridView control provides TextBox, CheckBox, Image, Button, ComboBox and Link columns with the corresponding cell types.

Multiple ways to display data

The DataGridView control can display unbound data stored in the control, data from a bound data source, or bound and unbound data together. You can also implement virtual mode in the DataGridView control to provide custom data management.

Multiple ways to customize the display and work with data

The DataGridView control provides many properties and events that enable you to specify how data is formatted and displayed.

In addition, the DataGridView control provides multiple ways to work with your data. For example, you can:

§         sort data with corresponding sort glyph

§         enable selection modes by row, column or cell; multi-selection or single selection

§         copy content to the clipboard in multiple formats including text, CSV (comma separated value) & HTML

§         change the way users edit cell content

Multiple options for changing cell, row, column, and header appearance and behavior

The DataGridView control enables you to work with individual grid components in numerous ways. For example, you can:

§         freeze rows and columns to prevent them from scrolling

§         hide rows, columns, and headers

§         change the way row, column, and header sizes are adjusted based upon size

§         change the way users make selections

§         provide ToolTips and shortcut menus for individual cells, rows, and columns

§         customize the border styles of cell, rows and columns

Rich extensibility support

The DataGridView control provides the infrastructure to extend and customize the grid. For example, you can:

§         handle custom painting events to provide a custom look and feel to the cells, columns and rows

§         derive from one of the built-in cell types to provide additional behavior

§         implement custom interfaces to create a brand new editing experience

2                  Structure of DGV

The DataGridView control and its related classes are designed to be a flexible, extensible system for displaying and editing tabular data. These classes are all contained in the System.Windows.Forms namespace, and they are all named with the "DataGridView" prefix.

2.1           Architecture Elements

The primary DataGridView companion classes derive from DataGridViewElement.

 The DataGridViewElement class provides a reference to the parent DataGridView control and has a State property, which holds a value that represents a combination of values from the DataGridViewElementStates enumeration.

2.2           Cells and Bands

The DataGridView control comprises two fundamental kinds of objects: cells and bands. All cells derive from the DataGridViewCell base class. The two kinds of bands, DataGridViewColumn and DataGridViewRow, both derive from the DataGridViewBand base class.

The DataGridView control interoperates with several classes, but the most commonly encountered are DataGridViewCell, DataGridViewColumn, and DataGridViewRow.

2.3           DataGridViewCell

The cell is the fundamental unit of interaction for the DataGridView. Display is centered on cells, and data entry is often performed through cells. You can access cells by using the Cells collection of the DataGridViewRow class, and you can access the selected cells by using the SelectedCells collection of the DataGridView control.


The DataGridViewCell class diagram

Cell Related Classes and Properties

The DataGridViewCell type is an abstract base class, from which all cell types derive. DataGridViewCell and its derived types are not Windoyws Forms controls, but some host Windows Forms controls. Any editing functionality supported by a cell is typically handled by a hosted control.

DataGridViewCell objects do not control their own appearance and painting features in the same way as Windows Forms controls. Instead, the DataGridView is responsible for the appearance of its DataGridViewCell objects. You can significantly affect the appearance and behavior of cells by interacting with the DataGridView control's properties and events. When you have special requirements for customizations that are beyond the capabilities of the DataGridView control, you can implement your own class that derives from DataGridViewCell or one of its child classes.

2.3.1      How a DataGridViewCell works

An important part of understanding the structure of the DataGridView is to understand how a DataGridViewCell works.

A Cell’s Value

At the root of a cell is its value. For cells in a column that is not databound and the grid is not in virtual mode the cells actually store the value in the cell instance. For databound cells the cell doesn’t “know” or keep the value is at all. Anytime the cell’s value is needed the grid goes to the datasource and looks up the value for the column and row and returns that as the cell’s value. In virtual mode this routine is very similar except the grid raises the CellValueNeeded event to get the cell’s value. At the cell level, all of this is controlled via the DataGridViewCell::GetValue(...) method.

The data type for the cell’s Value property by default is of type object. When a column becomes databound its ValueType property is set which causes each cell’s ValueType to be updated. The value of the ValueType property is important for formatting.

Formatting for Display

Anytime the grid needs to know “how would this cell display” it needs to get its FormattedValue. This is a complex routine because formatting something on the screen usually needs to be converted to a string. For example, although you set a cell’s value to the integer value of 155 when 155 needs to be displayed it has to become formatted for the display. The cells and column’s FormattedValueType property determines the type that is used for display. Most columns use string, but the image and check box cells\columns have different values. The DataGridViewImageCell and column use Image as the default FormattedValueType since its painting code knows how to display an image. A checkbox cell\column’s FormattedValueType varies depending upon the value of ThreeState. At the cell level, all of this is controlled via the DataGridViewCell::GetFormattedValue(...) method.

By default, the DataGridView uses TypeConverters to convert a cell’s value to its formatted value. Retrieving the proper TypeConverter is based upon the cell’s ValueType and FormattedValueType properties.

For a cell, the FormattedValue is requested many times. Anytime the cell is painted or when a column needs to be autosized based upon the cell’s content; the FormattedValue is even needed when determining if the mouse is over the cell content or not. Anytime the FormattedValue is required the DataGridView raises the CellFormatting event. This provides you with the opportunity to modify how the cell is formatted.

If a cell cannot retrieve its formatted value correctly it raises the DataError event.

Part of formatting a cell for display is understanding what the preferred size of the cell is. The preferred size is a combination of the cell’s FormattedValue, any padding or additional display and the borders.

Painting the Display

After the FormattedValue is retrieved the cell’s responsible for painting the cell’s content. The cell determines the correct style to paint with (see the Styling section later in this document) and paints the cell. It is important to note that if a cell does not paint itself then nothing is painted. A row or column performs no painting, so ensure that at least a background is painted in the cell otherwise the rectangle remains invalidated (unpainted).

Parsing the Display

After the user interacts with a cell at some point the user will edit a cell’s value. One important thing to note is that the user in reality is editing the cell’s FormattedValue. When committing the value the FormattedValue has to be converted back to the cell’s value. This is called parsing. At the cell level, all of this is controlled via the DataGridViewCell:: ParseFormattedValue (int rowIndex) method.

By default, TypeConverters are used again to parse the formatted value to the real value. The DataGridView raises the CellParsing event at this time to provide you with the opportunity to modify how the cell’s formatted value is parsed.

If a cell cannot correctly parse the formatted value it raises the DataError event.

Common questions and scenarios

1)       How do I prevent a particular cell from being editable?

2)       How do I disable a cell?

3)       How do I restrict user from setting focus to a specific cell?

4)       How do I show controls in all cells regardless of edit?

5)       Why does the cell text show up with “square” characters where they should be new lines?

6)       How do I show icon and text in the same cell?

2.4           DataGridViewColumn

The schema of the DataGridView control's attached data store is expressed in the DataGridView control's columns. You can access the DataGridView control's columns by using the Columns collection. You can access the selected columns by using the SelectedColumns collection.

The DataGridViewColumn class diagram

Column Related Classes and Properties

 Some of the key cell types have corresponding column types. These are derived from the DataGridViewColumn base class.

Common questions and scenarios

1)       How do I hide a column?

2)       How do I prevent the user from sorting on a column?

3)       How do I sort on multiple columns?

2.5           DataGridView Editing Controls

Cells that support advanced editing functionality typically use a hosted control that is derived from a Windows Forms control. These controls also implement the IDataGridViewEditingControl interface.

The DataGridView Editing Control Class diagram

Classes that implement Editing Controls

 The following editing controls are provided with the DataGridView control:

The following table illustrates the relationship among cell types, column types, and editing controls.

Cell type

Hosted control

Column type

DataGridViewButtonCell

n/a

DataGridViewButtonColumn

DataGridViewCheckBoxCell

n/a

DataGridViewCheckBoxColumn

DataGridViewComboBoxCell

DataGridViewComboBoxEditingControl

DataGridViewComboBoxColumn

DataGridViewImageCell

n/a

DataGridViewImageColumn

DataGridViewLinkCell

n/a

DataGridViewLinkColumn

DataGridViewTextBoxCell

DataGridViewTextBoxEditingControl

DataGridViewTextBoxColumn

Common questions and scenarios

1)       How do I hook up events on the editing control?

2)       When should I remove event handlers from the editing control?

3)       How do I handle the SelectedIndexChanged event?

4)       How do I show controls in all cells regardless of edit?

2.6           DataGridViewRow

The DataGridViewRow class displays a record's data fields from the data store to which the DataGridView control is attached. You can access the DataGridView control's rows by using the Rows collection. You can access the selected rows by using the SelectedRows collection.

The DataGridViewColumn class diagram

Row Related Classes and Properties

You can derive your own types from the DataGridViewRow class, although this will typically not be necessary. The DataGridView control has several row-related events and properties for customizing the behavior of its DataGridViewRow objects.

If you enable the DataGridView control's AllowUserToAddRows property, a special row for adding new rows appears as the last row. This row is part of the Rows collection, but it has special functionality that may require your attention. For more information, see Using the Row for New Records in the Windows Forms DataGridView Control.

Common questions and scenarios

1)       How do I perform drag and drop reorder of rows?

3                  Out of the box column/cell types

The DataGridView control uses several column types to display its information and enable users to modify or add information.

When you bind a DataGridView control and set the AutoGenerateColumns property to true, columns are automatically generated using default column types appropriate for the data types contained in the bound data source.

You can also create instances of any of the column classes yourself and add them to the collection returned by the Columns property. You can create these instances for use as unbound columns, or you can manually bind them. Manually bound columns are useful, for example, when you want to replace an automatically generated column of one type with a column of another type.

The following table describes the various column classes available for use in the DataGridView control:

Class

Description

DataGridViewTextBoxColumn

Used with text-based values. Generated automatically when binding to numbers and strings.

DataGridViewCheckBoxColumn

Used with Boolean and CheckState values. Generated automatically when binding to values of these types.

DataGridViewImageColumn

Used to display images. Generated automatically when binding to byte arrays, Image objects, or Icon objects.

DataGridViewButtonColumn

Used to display buttons in cells. Not automatically generated when binding. Typically used as unbound columns.

DataGridViewComboBoxColumn

Used to display drop-down lists in cells. Not automatically generated when binding. Typically data-bound manually.

DataGridViewLinkColumn

Used to display links in cells. Not automatically generated when binding. Typically data-bound manually.

Your custom column type

You can create your own column class by inheriting the DataGridViewColumn class or any of its derived classes to provide custom appearance, behavior, or hosted controls. For more information, see How to: Customize Cells and Columns in the Windows Forms DataGridView Control by Extending Their Behavior and Appearance

Common questions and scenarios

1)       How do I hide a column?

2)       How do I prevent a particular cell from being editable?

3)       How do I restrict user from setting focus to a specific cell?

4)       How do I make the last column wide enough to occupy all the remaining client area of the grid?

3.1           DataGridViewTextBoxColumn

The DataGridViewTextBoxColumn is a general-purpose column type for use with text-based values such as numbers and strings. In editing mode, a TextBox control is displayed in the active cell, enabling users to modify the cell value.

Cell values are automatically converted to strings for display. Values entered or modified by the user are automatically parsed to create a cell value of the appropriate data type. You can customize these conversions by handling the CellFormatting and CellParsing events of the DataGridView control.

The cell value data type of a column is specified in the ValueType property of the column.

Common questions and scenarios

1)       How do I have the cell text wrap?

2)       Why does the cell text show up with “square” characters where they should be new lines?

3)       How do I show icon and text in the same cell?

4)       How do I restrict user from setting focus to a specific cell?

3.2           DataGridViewCheckBoxColumn

The DataGridViewCheckBoxColumn is used with Boolean and CheckState values. Boolean values display as two-state or three-state check boxes, depending on the value of the ThreeState property. When the column is bound to CheckState values, the ThreeState property value is true by default.

Typically, check box cell values are intended either for storage, like any other data, or for performing bulk operations. If you want to respond immediately when users click a check box cell, you can handle the CellClick event, but this event occurs before the cell value is updated. If you need the new value at the time of the click, one option is to calculate what the expected value will be based on the current value. Another approach is to commit the change immediately, and handle the CellValueChanged event to respond to it. To commit the change when the cell is clicked, you must handle the CurrentCellDirtyStateChanged event. In the handler, if the current cell is a check box cell, call the CommitEdit method and pass in the Commit value.

3.3           DataGridViewImageColumn

The DataGridViewImageColumn is used to display images. Image columns can be populated automatically from a data source, populated manually for unbound columns, or populated dynamically in a handler for the CellFormatting event.

The automatic population of an image column from a data source works with byte arrays in a variety of image formats, including all formats supported by the Image class and the OLE Picture format used by Microsoft® Access and the Northwind sample database.

Populating an image column manually is useful when you want to provide the functionality of a DataGridViewButtonColumn, but with a customized appearance. You can handle the CellClick event to respond to clicks within an image cell.

Populating the cells of an image column in a handler for the CellFormatting event is useful when you want to provide images for calculated values or values in non-image formats. For example, you may have a "Risk" column with string values such as "high", "middle", and "low" that you want to display as icons. Alternately, you may have an "Image" column that contains the locations of images that must be loaded rather than the binary content of the images.

Common questions and scenarios

1)       How do I make the image column not show any images?

3.4           DataGridViewButtonColumn

With the DataGridViewButtonColumn, you can display a column of cells that contain buttons. This is useful when you want to provide an easy way for your users to perform actions on particular records, such as placing an order or displaying child records in a separate window.

Button columns are not generated automatically when data-binding a DataGridView control. To use button columns, you must create them manually and add them to the collection returned by the Columns property.

You can respond to user clicks in button cells by handling the CellClick event.

3.5           DataGridViewComboBoxColumn

With the DataGridViewComboBoxColumn, you can display a column of cells that contain drop-down list boxes. This is useful for data entry in fields that can only contain particular values, such as the Category column of the Products table in the Northwind sample database.

You can populate the drop-down list used for all cells the same way you would populate a ComboBox drop-down list, either manually through the collection returned by the Items property, or by binding it to a data source through the DataSource, DisplayMember, and ValueMember properties. For more information, see ComboBox Control (Windows Forms).

You can bind the actual cell values to the data source used by the DataGridView control by setting the DataPropertyName property of the DataGridViewComboBoxColumn.

Combo box columns are not generated automatically when data-binding a DataGridView control. To use combo box columns, you must create them manually and add them to the collection returned by the Columns property. Alternatively you can use the designer and change a column type to a combo box column and set properties accordingly.

3.5.1      DataErrors and the combo box column

Sometimes when working the DataGridViewComboBoxColumn and modifying either the cell’s value or the combo box items collection,  sometimes the DataError event might be raised. This is by design because of the data validation that the combo box cell performs. When the combo box cell attempts to draw its content it has to go from the cell value to the formatted value. This conversion requires looking up the value in the combo box items and getting the display value for the item. During this process, if the cell’s value cannot be found in the combo box items collection it raises the DataError event. Ignoring the DataError event might keep the cell from displaying the correct formatted value.

Common questions and scenarios

1)       How do I enable typing in the combo box cell?

2)       How do I handle the SelectedIndexChanged event?

3)       How do I have a combo box column display a sub set of data based upon the value of a different combo box column?

3.6           DataGridViewLinkColumn

With the DataGridViewLinkColumn, you can display a column of cells that contain hyperlinks. This is useful for URL values in the data source or as an alternative to the button column for special behaviors such as opening a window with child records.

Link columns are not generated automatically when data-binding a DataGridView control. To use link columns, you must create them manually and add them to the collection returned by the Columns property.

You can respond to user clicks on links by handling the CellContentClick event. This event is distinct from the CellClick and CellMouseClick events, which occur when a user clicks anywhere in a cell.

The DataGridViewLinkColumn class provides several properties for modifying the appearance of links before, during, and after they are clicked.

4                  Working with Data

In most cases you’ll be using the DataGridView with data. There are many tasks that you might need to do when working with your data in the DataGridView. You might need to validate data that the user entered or maybe you might need to format the data. The DataGridView can display data in three distinct modes: bound, unbound, and virtual. Each mode has its own features and reasons to choose it over the other. Regardless of databound mode it is common for the grid to raise the DataError event when something goes wrong when working with data. Understanding why this event occurs will make the event more helpful.

4.1           Data Entry and Validation Events

When the user enters data – either at the row or cell level you might want to validate the data and maybe inform the user about invalid data. Like normal Windows Forms, there are Validating and Validated events at the cell and row level. Validating events can be canceled. There are also Enter and Leave events for when the user moves between cells or rows. Lastly there are events for when the user starts editing a cell. Understand the order of all these events will be helpful.

4.1.1      Order of Validation Events

 The following identifies the order of validation, enter/leave and begin/end edit events. The EditMode is EditOnEnter.

When moving from cell to cell (in the same row)

1)       Cell Leave (old cell)

2)       Cell Validating/ed (old cell)

3)       Cell EndEdit (old cell)

4)       Cell Enter (new cell)

5)       Cell BeginEdit (new cell)

When moving from one row to another you get:

1)       Cell Leave (old cell), Row leave (old row)

2)       Cell Validating/ed (old cell)

3)       Cell EndEdit (old cell)

4)       Row Validating/ed (old row)

5)       Row Enter (new row)

6)       Cell Enter (new cell)

7)       Cell BeginEdit (new cell)

4.1.2      Validating Data

When validating user data, you will usually validate the data at the cell level when the grid is not databound, and at the row level when the grid is databound. Sometimes when databound you will perform validation both at the cell and row level.

4.1.2.1    Displaying error information

When you do encounter data that is invalid you usually notify the user about it. There are many ways to do this; the conventional way is to use a message box. The DataGridview has the ability to show an error icon for the cell and rows to indicate that invalid data was entered. The error icon has a tooltip associated with it to provide informational about what is in error:

Common questions and scenarios

1)       How do I show the error icon when the user is editing the cell?

4.1.3      Data Entry in the New Row

When you use a DataGridView for editing data in your application, you will often want to give your users the ability to add new rows of data to the data store. The DataGridView control supports this functionality by providing a row for new records, which is always shown as the last row. It is marked with an asterisk (*) symbol in its row header. The following sections discuss some of the things you should consider when you program with the row for new records enabled.

4.1.3.1       Displaying the Row for New Records

Use the AllowUserToAddRows property to indicate whether the row for new records is displayed. The default value of this property is true.

The new row is the last row in the grid:

For the data bound case, the row for new records will be shown if the AllowUserToAddRows property of the control and the IBindingList.AllowNew property of the data source are both true. If either is false then the row will not be shown.

4.1.3.2       Populating the Row for New Records with Default Data

When the user selects the row for new records as the current row, the DataGridView control raises the DefaultValuesNeeded event. This event provides access to the new DataGridViewRow and enables you to populate the new row with default data.

The following code example demonstrates how to specify default values for new rows using the DefaultValuesNeeded event.

private void dataGridView1_DefaultValuesNeeded(object sender,

                                  DataGridViewRowEventArgs e)

{

    e.Row.Cells["Region"].Value = "WA";

    e.Row.Cells["City"].Value = " Redmond";

    e.Row.Cells["PostalCode"].Value = "98052-6399";

    e.Row.Cells["Region"].Value = "NA";

    e.Row.Cells["Country"].Value = " USA ";

    e.Row.Cells["CustomerID"].Value = NewCustomerId();

}

4.1.3.3       The Rows Collection and the New Row

The row for new records is contained in the DataGridView control's Rows collection, so the following line returns the new row:

DataGridViewRow row = dataGridView1.Rows[dataGridView1.Rows.Count - 1];

Even though the new row is in the rows collection it does behaves differently in two respects:

4.1.3.4       Typing in the New Row

Before a user starts to type in the new row the row’s IsNewRow property returns true. When the user starts to type in the new row, that row no longer is considered the new row, but a “new” new row is added:

When this “new” new row is added the UserAddedRow event fires with the Row event args property identifying the “new” new row. If the user hits the Escape key at this stage the “new” new row is removed. This causes the UserDeletingRow event to fire with the Row event args property identifying the “new” new row.

4.1.3.5       Visual Customization of the Row for New Records

When the row for new records is created, it is based on the row specified by the RowTemplate property. Any cell styles that are not specified for this row are inherited from other properties. For more information about cell style inheritance, see the Cell Styles topic later in this document.

The initial values displayed by cells in the row for new records are retrieved from each cell's DefaultNewRowValue property. For cells of type DataGridViewImageCell, this property returns a placeholder image. Otherwise, this property returns null. You can override this property to return a custom value. However, these initial values can be replaced by a DefaultValuesNeeded event handler when focus enters the row for new records.

The standard icons for this row's header, which are an arrow or an asterisk, are not exposed publicly. If you want to customize the icons, you will need to create a custom DataGridViewRowHeaderCell class.

The standard icons use the ForeColor property of the DataGridViewCellStyle in use by the row header cell. The standard icons are not rendered if there is not enough space to display them completely.

If the row header cell has a string value set, and if there is not enough room for both the text and icon, the icon is dropped first.

4.1.3.6       Sorting the New Row

In unbound mode, new records will always be added to the end of the DataGridView even if the user has sorted the content of the DataGridView. The user will need to apply the sort again in order to sort the row to the correct position; this behavior is similar to that of the ListView control.

In data bound and virtual modes, the insertion behavior when a sort is applied will be dependent on the implementation of the data model. For ADO.NET, the row is immediately sorted into the correct position.

4.1.3.7       Other Notes on the Row for New Records

You cannot set the Visible property of this row to false. An InvalidOperationException is raised if this is attempted.

The row for new records is always created in the unselected state.

4.1.3.8       Virtual Mode

If you are implementing virtual mode, you will need to track when a row for new records is needed in the data model and when to roll back the addition of the row. The exact implementation of this functionality depends on the implementation of the data model and its transaction semantics, for example, whether commit scope is at the cell or row level. See the Virtual Mode topic later in this document for more info.

4.2           Working with Null values

When working with datasource such as a database or a business object it is common to deal with null values. Null values can be an actual null (nothing in VB) or a database “null value” (DBNull.Value).  When working with these values you’ll need to decide how you will display them. In addition there are valid reasons for when you’ll want to write a null value. Using the cell style’s NullValue and DataSourceNullValue properties you can change how the DataGridView works with null values.

4.2.1      NullValue

The DataGridViewCellStyle.NullValue property should have been called FormattedNullValue, but it was too late to make this change. Hopefully this provides a clue into how the NullValue is used – at formatting time. When a cell’s value is “null” (equal to Null or DBNull.Value) the value in the DataGridViewCellStyle.NullValue property is used for display. The default value of this property is based upon the column:

DataGridView column

Column’s DefaultCellStyle.NullValue

TextBoxColumn

String.Empty (“”)

ImageColumn

Null image ()

ComboBoxColumn

String.Empty (“”)

ButtonColumn

String.Empty (“”)

LinkColumn

String.Empty (“”)

CheckBoxColumn

Default is based upon the ThreeState property. If true default value is CheckState.Indeterminate; otherwise it is false (unchecked).

What is important to understand is that the NullValue is also used when the user enters data. For example, if the user enters String.Empty into a text box cell then Null is entered as the cell’s value (check out the DataSourceNullValue below for more details on what is actually entered as the cell’s value).

4.2.2      DataSourceNullValue

The DataGridViewCellStyle.DataSourceNullValue property could have been called ParseNullValue if the other property was FormattedNullValue, but in the end DataSourceNullValue made good sense. The DataSourceNullValue property is used when writing the value of “Null” to the cell’s value. In databound scenarios