I was searching long and hard to find a good article on how to get a
GridViewCell in a
DataGridView to display a
ListView panel when editing column, similar to the one found here: http://msdn.microsoft.com/en-us/library/7tas5c80.aspx.
I ended up having to make it myself from scratch. At first I thought it would be a quite straight forward job, but I was proven wrong. Since I normally benefit from what others add to Code Project, it is now my time to give something back.
The sample code is quite simple, but it shows you how to implement a
ListView working similar to the date picker from Microsoft.
The reason for making this was a need for a better representation than what was available in a drop-list. I also want the possibility to edit values while selecting value. For this reason I wanted an advanced controller when editing a cell. In lack of any good samples, I decided to make one.
Using the code
Making the control
As with the DateTimePicker sample from Microsoft, I've made derived classes from
DataGridViewTextBoxCell to get my own control when editing the cell.
In addition I've overriden the function
PositionEditingControl in my cell to position the control where I want it.
public override void PositionEditingControl(bool setLocation, bool setSize,
Rectangle cellBounds, Rectangle cellClip, DataGridViewCellStyle cellStyle,
bool singleVerticalBorderAdded, bool singleHorizontalBorderAdded,
bool isFirstDisplayedColumn, bool isFirstDisplayedRow)
size = new Size(cellBounds.Width + 100, 100);
location = new Point(cellBounds.Location.X, cellBounds.Location.Y + cellBounds.Height);
if ((location.Y + size.Height) > this.DataGridView.TopLevelControl.ClientSize.Height)
location.Y -= (size.Height + cellBounds.Height);
if ((location.X + size.Width) > this.DataGridView.TopLevelControl.ClientSize.Width)
location.X -= 100;
ctlSize = new Rectangle(location, size);
base.PositionEditingControl(setLocation, setSize, ctlSize, ctlSize, cellStyle,
if (m_control != null)
m_control.Location = location;
Getting value from control
I've chosen to fetch value from control when control is detached from the cell.
public override void DetachEditingControl()
CustomViewControl ctl = DataGridView.EditingControl as CustomViewControl;
if (ctl != null && ctl.SelectedItems.Count > 0)
this.Value = ctl.SelectedItems.SubItems.ToString();
ctl.EditingControlFormattedValue = String.Empty;
Then i listen to the
CellEndEdit event on my
DataGridView and fetch the value from the cell there.
private void m_gridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
gridView = sender as DataGridView;
if (gridView != null)
cell = gridView.CurrentCell as CustomViewCell;
if (cell != null && cell.Value != null)
string sValue = cell.Value as string;
Placing the user defined control outside of DataGridView
To get the ListView placed above the
DataGridView, not being limited by the borders of the
DataGridView, I add the control to the top level control, and remove it when I'm done editing.
protected override void OnCreateControl()
topLevel = this.TopLevelControl as Form1;
if (topLevel != null && this.Parent != topLevel)
protected override void OnLeave(EventArgs e)
if (m_dataGridView.IsCurrentCellInEditMode && !m_boEnded)
parent = this.Parent as Form1;
if (parent != null)
In my case I want to use different inherited listviews on different columns. I tried making a column control where I use generics to specify what kind of controller I want to use. To do this I made a control that inherits from
IDataGridViewEditingControl and adds the desired control to that panel. This looked promising, but there are some issues to it. The sample contains the halfway functioning generics control. If anyone know how to get it working, then please tell me how.
If this is solved, than it will be possible to make any panel the control used when editing a
While the normal control is created every time a cell is edited and deleted when edit is ended, when adding the control as an on the panel, some of the basic handling from windows fails.
Issues to this solution are:
- Flickering when activating control
- Closing control when moving outside of window