Download DataGridComboBoxTest.zip I recently needed a datagrid combobox for a project that I was working on. Out of box, ASP.Net (2003 and 2005) does not provide such functionality and I had to create my own. There are quite a few articles online talking about how to create a combobox cell within a datagrid control. After some research, it seemed that an article Tailor Your DataGrid Apps Using Table Style and Custom Column Style Objects on MSDN magazine was the most promising one. However, after I incorporated the code into an application that I was writing, I noticed that there was one very annoying bug in the code: when you select a row by clicking the row header, the combo box is automatically selected. It works fine as long as you do not delete any rows. If you delete a row, the content of the combobox that belongs to the deleted row will automatically replace the current row (which shifted up after the original row was deleted). Even worse, if you commit the change, the row with the incorrect combobox value will be saved and the original value is lost. You can duplicate this error by running the sample program in the article. After some investigation, I was convinced that this was caused by the combobox not losing focus when the row was selected. To fix this problem, I needed a way to tell whether a row header had been clicked or it was just the cell being selected. If the row was selected, the combobox needs to become invisible. To achieve this, I added a property RowSelected to the original ComboBoxColumn class. And changed the overridden function Edit to show the combobox only when the row is not currently selected. I also added an event handler to detect whether the mouse was clicked on the column. And whenever the mouse was first clicked, the combobox was hidden (note that this event fires before the Edit event is fired so that the visibility of the combobox can be set to the correct value later when the Edit event fires). This is necessary for the combobox to lose its focus if it is first clicked and then the row being selected by right clicking the mouse. There was also a small bug in the original code in the SetColumnValueAtRow function. Originally the code calls base.SetColumnValueAtRow(source, rowNum, s) to set the value at current row, however when the grid was first created, the rowNum is 0 and does not necessarily reflect the contents index of the combobox. To use this enhanced control, you unfortunately will have to do a little more work in your code. Because there is no way inside a DatagridColumn class to tell whether the whole row is selected, you have to add a MouseDown event handler inside the code where you reference the DatagridComboBox. In the example I provided with this article, you would do something like this:

private void dg_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { Point p = new Point(e.X, e.Y); DataGrid.HitTestInfo hinfo = (sender as DataGrid).HitTest(p); DataGridCell dgc; if (hinfo.Type == DataGrid.HitTestType.RowHeader) { dg.Select(dg.CurrentRowIndex); dgc = dg.CurrentCell; GridColumnStylesCollection s = dg.TableStyles[0].GridColumnStyles; MSDNMag.DataGridDemo.DataGridComboBoxColumn col = (MSDNMag.DataGridDemo.DataGridComboBoxColumn) s[0]; col.RowSelected = true; } else { dgc = dg.CurrentCell; GridColumnStylesCollection s = dg.TableStyles[0].GridColumnStyles; MSDNMag.DataGridDemo.DataGridComboBoxColumn col = (MSDNMag.DataGridDemo.DataGridComboBoxColumn) s[0]; col.RowSelected = false; } }

This code basically sets the RowSelected property in the ComboBoxColumn control. You can download the sample code and try out yourself.

Be Sociable, Share!