This is just a quick update to announce another update to my Drop-Down Controls project. By request (and because I always enjoy a challenge), i’ve added custom DataGridView
column types for the ComboTreeBox
and GroupedComboBox
controls. This means that you can now use these controls from within a DataGridView
, taking advantage of the automatic support for reading/writing to a data source that comes with it.
Creating custom column types
The general process for implementing a custom DataGridView
column type is as follows:
- Create a class that derives from
DataGridViewColumn
that will represent the column and properties that apply to all of its cells. Be sure to override theClone
method. - Create a class that derives from
DataGridViewCell
that will represent the individual cells, including any properties that override those inherited from the column. As above, override theClone
method. You will also need to override thePaint
method to draw the cell’s “normal” appearance (i.e. when the cell is not in edit mode). In the constructor for the column class, set theCellTemplate
property to a new instance of the cell class. - Create a class that derives from
Control
and implements theIDataGridViewEditingControl
interface, which will be responsible for editing a cell’s value. (Alternatively, the cell can implement theIDataGridViewEditingCell
interface if it provides in-place editing… but this is only useful when the editing UI is very simple.) Override theEditType
property of the cell class to return the type of the editing control. Also override theInitializeEditingControl
method to set the initial value of the control and set up any other behaviours.
In all of the above, you can use a more derived base class than those mentioned (e.g. DataGridViewTextBoxColumn
, DataGridViewComboBoxCell
, DateTimePicker
, etc). In this case, since I already have controls to use as editors, I will extend those. However, for the column and cell classes, it’s easier to start from scratch.
GroupedComboBoxColumn
The first custom column type I added is based on my GroupedComboBox control. Itself extending the built-in ComboBox
control, it behaves very much like the DataGridViewComboBoxColumn
. However, because the control does some custom painting and manipulation of the data source, it was easier to implement separately from the built-in column type.
Unlike the built-in column, there is no Items
property on this column type. Since the grouping functionality relies on being bound to a data source, it makes sense to do this exclusively via the DataSource
property. As with the GroupedComboBox
itself, you can set the DisplayMember
, ValueMember
and GroupMember
properties to control how the list items behave. All of these properties are optional (although you will not get the grouping behaviour unless you set the latter one).
You can override all of these properties for individual cells; setting the cell’s properties to null
(the default) will cause the values to be inherited from the owning column.
ComboTreeBoxColumn
Secondly, the other column type is based on my ComboTreeBox control. There are various challenges associated with populating hierarchical views from flat lists/tables:
The nodes displayed in the drop-down for this column type must be set manually. As with the previous column type, however, you can override the Nodes
property for cells on an individual basis (controlled by the UseColumnNodes
property).
In terms of actually selecting nodes, the underlying value type for cells in the ComboTreeBoxColumn
is simply String
. You select a specific node by its path, the format of which is determined by both the PathSeparator
and UseNodeNamesForPath
properties. This is also used for the formatted value of the cells. The cell itself can display either the path or the node text, depending on the value of ShowPath
. All of this means that the underlying cell values (and therefore the values in the data source for the grid) must be path strings.
e.g. The path string Fruit\Citrus\Orange
selects the node with the text “Orange” whose immediate parent node is “Citrus” and whose grandparent node is “Fruit”.
Path strings can be translated to/from ComboTreeNode
via the GetFullPath
and GetNodeAt
methods on the ComboTreeBox
control.
Download
The latest version of the drop-down controls can be downloaded from the project page.