Roland Weigelt

Born to Code

News

.NET related Links

Archives

Custom Editing Behavior for DataGridView TextBox Columns

I’m currently working on a hobby project where I’m displaying a list of files in a way similar to the “details” view of Windows Explorer. For various reasons I’m using a DataGridView instead of a ListView, and while configuring the DataGridView to look like a ListView wasn’t much of a problem, there’s one thing that got on my nerves, which is the behavior of textbox cells in edit mode: It is much too easy to leave the edit mode accidentally, simply by pressing the cursor keys at the wrong time. For example when the text caret is positioned behind the last character of the textbox cell content, and you press the right arrow key: the focus then moves to the next cell. There are certainly use cases for this behavior, but for my purposes I wanted the text caret to be “captured” inside the textbox in edit mode until you press Enter, Tab or Escape (or use the mouse to click another cell).

The nice thing about the DataGridView is that you can tweak it a lot by deriving from existing classes for cells, columns and editing controls, overriding certain methods. In my case I suspected that the DataGridViewTextBoxEditingControl (derived from TextBox) would contain special code to determine when the cell should leave edit mode. As I didn’t know what to search the documentation for (and I was too impatient to read it completely, to be honest), I fired up Lutz Roeder’s Reflector and took a look at the decompiled code of the class members. With the option “Show Inherited Members” switched off it took me only a couple of seconds to come across the code of the EditingControlWantsInputKey method which looked exactly like what I was expecting (lucky me: it was the 4th member in the list ;-).

So here are the steps to change the behavior of the editing control:

First derive a class from DataGridViewTextBoxEditingControl and override the EditingControlWantsInputKey method:

public class CustomDataGridViewTextBoxEditingControl
: DataGridViewTextBoxEditingControl
{
public override bool EditingControlWantsInputKey( Keys keyData, bool dataGridViewWantsInputKey )
{
switch (keyData & Keys.KeyCode)
{
case Keys.Prior:
case Keys.Next:
case Keys.End:
case Keys.Home:
case Keys.Left:
case Keys.Up:
case Keys.Right:
case Keys.Down:
case Keys.Delete:
return true;
}
return base.EditingControlWantsInputKey( keyData, dataGridViewWantsInputKey );
}
}

Then derive a class from DataGridViewTextBoxCell and override the EditType property to use the customized editing control:

public class CustomDataGridViewTextBoxCell
: DataGridViewTextBoxCell
{
public override Type EditType
{
get { return typeof( CustomDataGridViewTextBoxEditingControl ); }
}
}

Finally derive a class from DataGridViewTextBoxColumn to be able to use the new cell type.

public class CustomDataGridViewTextBoxColumn
: DataGridViewColumn
{
public CustomDataGridViewTextBoxColumn()
: base( new CustomDataGridViewTextBoxCell() )
{
}
}

You can now use the new column type in your code as a replacement of the stock DataGridViewTextBoxColumn (the new type appears in the drop down lists for column types in the designer dialogs of the DataGridView control).

A demo project is available here, showing a DataGridView with a normal DataGridViewTextBoxColumn and the CustomDataGridViewTextBoxColumn next to each other, so you can compare the different behaviors.

Comments

Hamid said:

would you please help me that how can i control textchange and keypress for datagridviewcell in programm?

# March 23, 2007 2:51 PM

WeigeltRo said:

Hi Hamid,

could you please give me some more details so I get a better understanding of the problem you want to solve?

Roland

# March 24, 2007 5:28 AM

Todd Beaulieu said:

Excellent tip. Was exactly what I needed.

Note that if you're programmatically adding columns, you can do it as follows:

DataGridViewNumericTextBoxColumn numCol;

numCol = new DataGridViewNumericTextBoxColumn();

numCol.Name = "AdjustedScore";

numCol.HeaderText = "Adjusted Score";

Grid1.Columns.Add(numCol);

# April 9, 2007 1:58 PM