2008-03-24

An amusing bought with the DataGridView control

As usual, WinForms GUI programming is a terrible PIA. Even worse is the flagship of all controls the great beast known as the DataGridView. Working with the DataGridView bends your mind like offensive cutlery at Uri Geller's dinner table.

During my most recent encounter with this control of the third kind, I needed to use a ComboBox column, and that column needed to have an effect on the contents of the other controls. Normally, you could just hook up a cellvaluechanged event or something of that nature, but that doesn't work out on a ComboBox control in a DataGridView column... There's no event that would fire when a user selected an item in the dropdown. Only after the user selected the item, then refocused on some other control.

That was annoying. Too many clicks for the user! When I select the item in the dropdown, the row should react, I shouldn't have to click elsewhere.

So here's a quick example of what I did to get that working. In the example, we handle the datagridview's EditControlShowing event, then grab a reference to the combobox, then unwire any previous events we may have hooked up to SelectionChangeCommitted, then wire the event. In the SelectionChangeCommitted event we call _dataGridView.EndEdit() to effect the other rows.

Enjoy!



public class Example
{
///
/// Constructor
///

public Example()
{
_dataGridView = new DataGridView();

// setup the datagridview here.
DataGridViewComboBoxColumn fooColumn = new DataGridViewComboBoxColumn();
fooColumn.Name = "Foo";
fooColumn.ValueType = typeof(String);
fooColumn.HeaderText = "Foo";
fooColumn.Items.Add("Bar");
fooColumn.Items.Add("Baz");
fooColumn.Items.Add("Fizz");
fooColumn.Items.Add("Buzz");
fooColumn.Items.Add("FizzBuzz");
fooColumn.DefaultCellStyle.NullValue = "Bar";

_dataGridView.Columns.Add(fooColumn);

// hook up editing control showing event
_dataGridView.EditingControlShowing += new DataGridViewEditingControlShowingEventHandler(_dataGridView_EditingControlShowing);

// create a delegate for the method that will handle the event
_comboBoxSelectDelegate = new EventHandler(combo_SelectionChangeCommitted);
}

private DataGridView _dataGridView;
private EventHandler _comboBoxSelectDelegate;

void _dataGridView_EditingControlShowing(object sender, DataGridViewEditingControlShowingEventArgs e)
{
// get the control from the event args.

ComboBox combo = e.Control as ComboBox;


if (combo != null)
{
// remove the event subscription if it exists.
combo.SelectionChangeCommitted -= comboSelectDelegate;

// add a subscription to the event
combo.SelectionChangeCommitted += comboSelectDelegate;
}
}

void combo_SelectionChangeCommitted(object sender, EventArgs e)
{
// handle the event, and end edit mode
_dataGridView.EndEdit();
}
}

1 comment:

Jolinar said...

Hello,

Still, you will get the bug described in the following link:

http://support.microsoft.com/kb/948869