Need a DataGridView Custom Column of Type ListView or CheckedListBox
- I am attempting to write a new DataGridView custom column type based on the samples I have found so far but cannot get a ListView or CheckListBox to work correctly. One issue is that the list needs to be bound to a data source that is different from the containing DataGridView. I have not been able to locate any code samples that do this. Can someone kindly point me in the right direction?
The Microsoft code sample showing a calendar custom column is good as far as it goes but does not support data binding in the manner I have described above.
Answers
Hi James,
In order to display ListView or CheckListBox in a DataGridView cell, you need to paint the cell by yourself. The following is a sample on how to embed CheckListBox in DataGridView cell. In this sample, I bind the DataGridView to a data source and bind the the custom DataGridViewColumn to a property of type List<string> in the data source.public class CheckedListBoxColumn : DataGridViewColumn { public CheckedListBoxColumn() : base(new CheckedListBoxCell()) { } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if (value != null && !value.GetType().IsAssignableFrom(typeof(CheckedListBoxCell))) { throw new InvalidCastException("Must be a CheckedListBoxCell"); } base.CellTemplate = value; } } } public class CheckedListBoxCell : DataGridViewCell { public CheckedListBoxCell() : base() { } public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { // Set the value of the editing control to the current cell value. base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); CheckedListBoxEditingControl ctl = DataGridView.EditingControl as CheckedListBoxEditingControl; InitializeCheckedListBox(ctl,(ICollection)this.FormattedValue); } private void InitializeCheckedListBox(CheckedListBox ctrl,ICollection value) { ctrl.Items.Clear(); foreach(object obj in value) { ctrl.Items.Add(obj.ToString()); } ctrl.Tag = this.Value; } public override Type EditType { get { return typeof(CheckedListBoxEditingControl); } } protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) { if (value == null) { return new List<object>(); } return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context); } public override Type FormattedValueType { get { return typeof(ICollection); } } public override Type ValueType { get { return typeof(ICollection); } } private CheckedListBox internalControl; protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); graphics.FillRectangle(new SolidBrush(cellStyle.BackColor), cellBounds); if (internalControl == null) { internalControl = new CheckedListBox(); } internalControl.Items.Clear(); ICollection collection = value as ICollection; if (collection != null) { foreach (object obj in collection) { internalControl.Items.Add(obj); } Bitmap bmp = new Bitmap(cellBounds.Width, cellBounds.Height); internalControl.DrawToBitmap(bmp,new Rectangle(0,0,bmp.Width,bmp.Height)); graphics.DrawImage(bmp,cellBounds,new Rectangle(0,0,bmp.Width,bmp.Height),GraphicsUnit.Pixel); } } protected override void OnClick(DataGridViewCellEventArgs e) { this.DataGridView.BeginEdit(false); base.OnClick(e); } } class CheckedListBoxEditingControl : CheckedListBox, IDataGridViewEditingControl { DataGridView dataGridView; private bool valueChanged = false; int rowIndex; public CheckedListBoxEditingControl() { } // Implements the IDataGridViewEditingControl.EditingControlFormattedValue // property. public object EditingControlFormattedValue { get { return this.Tag; } set { // this.Tag = value; } } // Implements the // IDataGridViewEditingControl.GetEditingControlFormattedValue method. public object GetEditingControlFormattedValue( DataGridViewDataErrorContexts context) { return EditingControlFormattedValue; } // Implements the // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. public void ApplyCellStyleToEditingControl( DataGridViewCellStyle dataGridViewCellStyle) { this.Font = dataGridViewCellStyle.Font; this.ForeColor = dataGridViewCellStyle.ForeColor; this.BackColor = dataGridViewCellStyle.BackColor; } // Implements the IDataGridViewEditingControl.EditingControlRowIndex // property. public int EditingControlRowIndex { get { return rowIndex; } set { rowIndex = value; } } // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey // method. public bool EditingControlWantsInputKey( Keys key, bool dataGridViewWantsInputKey) { // Let the DateTimePicker handle the keys listed. switch (key & Keys.KeyCode) { case Keys.Left: case Keys.Up: case Keys.Down: case Keys.Right: case Keys.Home: case Keys.End: case Keys.PageDown: case Keys.PageUp: return true; default: return !dataGridViewWantsInputKey; } } // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit // method. public void PrepareEditingControlForEdit(bool selectAll) { // No preparation needs to be done. } // Implements the IDataGridViewEditingControl // .RepositionEditingControlOnValueChange property. public bool RepositionEditingControlOnValueChange { get { return false; } } // Implements the IDataGridViewEditingControl // .EditingControlDataGridView property. public DataGridView EditingControlDataGridView { get { return dataGridView; } set { dataGridView = value; } } // Implements the IDataGridViewEditingControl // .EditingControlValueChanged property. public bool EditingControlValueChanged { get { return valueChanged; } set { valuevalueChanged = value; } } // Implements the IDataGridViewEditingControl // .EditingPanelCursor property. public Cursor EditingPanelCursor { get { return base.Cursor; } } }
This is a just a start point. You may need to modify it to meet your actual requirement.If you have any question, please feel free to let me know.
- Marked As Answer byLinda LiuMSFT, ModeratorMonday, March 30, 2009 6:05 AM
All Replies
Hi James,
In order to display ListView or CheckListBox in a DataGridView cell, you need to paint the cell by yourself. The following is a sample on how to embed CheckListBox in DataGridView cell. In this sample, I bind the DataGridView to a data source and bind the the custom DataGridViewColumn to a property of type List<string> in the data source.public class CheckedListBoxColumn : DataGridViewColumn { public CheckedListBoxColumn() : base(new CheckedListBoxCell()) { } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if (value != null && !value.GetType().IsAssignableFrom(typeof(CheckedListBoxCell))) { throw new InvalidCastException("Must be a CheckedListBoxCell"); } base.CellTemplate = value; } } } public class CheckedListBoxCell : DataGridViewCell { public CheckedListBoxCell() : base() { } public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { // Set the value of the editing control to the current cell value. base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); CheckedListBoxEditingControl ctl = DataGridView.EditingControl as CheckedListBoxEditingControl; InitializeCheckedListBox(ctl,(ICollection)this.FormattedValue); } private void InitializeCheckedListBox(CheckedListBox ctrl,ICollection value) { ctrl.Items.Clear(); foreach(object obj in value) { ctrl.Items.Add(obj.ToString()); } ctrl.Tag = this.Value; } public override Type EditType { get { return typeof(CheckedListBoxEditingControl); } } protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, System.ComponentModel.TypeConverter valueTypeConverter, System.ComponentModel.TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) { if (value == null) { return new List<object>(); } return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context); } public override Type FormattedValueType { get { return typeof(ICollection); } } public override Type ValueType { get { return typeof(ICollection); } } private CheckedListBox internalControl; protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts) { base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts); graphics.FillRectangle(new SolidBrush(cellStyle.BackColor), cellBounds); if (internalControl == null) { internalControl = new CheckedListBox(); } internalControl.Items.Clear(); ICollection collection = value as ICollection; if (collection != null) { foreach (object obj in collection) { internalControl.Items.Add(obj); } Bitmap bmp = new Bitmap(cellBounds.Width, cellBounds.Height); internalControl.DrawToBitmap(bmp,new Rectangle(0,0,bmp.Width,bmp.Height)); graphics.DrawImage(bmp,cellBounds,new Rectangle(0,0,bmp.Width,bmp.Height),GraphicsUnit.Pixel); } } protected override void OnClick(DataGridViewCellEventArgs e) { this.DataGridView.BeginEdit(false); base.OnClick(e); } } class CheckedListBoxEditingControl : CheckedListBox, IDataGridViewEditingControl { DataGridView dataGridView; private bool valueChanged = false; int rowIndex; public CheckedListBoxEditingControl() { } // Implements the IDataGridViewEditingControl.EditingControlFormattedValue // property. public object EditingControlFormattedValue { get { return this.Tag; } set { // this.Tag = value; } } // Implements the // IDataGridViewEditingControl.GetEditingControlFormattedValue method. public object GetEditingControlFormattedValue( DataGridViewDataErrorContexts context) { return EditingControlFormattedValue; } // Implements the // IDataGridViewEditingControl.ApplyCellStyleToEditingControl method. public void ApplyCellStyleToEditingControl( DataGridViewCellStyle dataGridViewCellStyle) { this.Font = dataGridViewCellStyle.Font; this.ForeColor = dataGridViewCellStyle.ForeColor; this.BackColor = dataGridViewCellStyle.BackColor; } // Implements the IDataGridViewEditingControl.EditingControlRowIndex // property. public int EditingControlRowIndex { get { return rowIndex; } set { rowIndex = value; } } // Implements the IDataGridViewEditingControl.EditingControlWantsInputKey // method. public bool EditingControlWantsInputKey( Keys key, bool dataGridViewWantsInputKey) { // Let the DateTimePicker handle the keys listed. switch (key & Keys.KeyCode) { case Keys.Left: case Keys.Up: case Keys.Down: case Keys.Right: case Keys.Home: case Keys.End: case Keys.PageDown: case Keys.PageUp: return true; default: return !dataGridViewWantsInputKey; } } // Implements the IDataGridViewEditingControl.PrepareEditingControlForEdit // method. public void PrepareEditingControlForEdit(bool selectAll) { // No preparation needs to be done. } // Implements the IDataGridViewEditingControl // .RepositionEditingControlOnValueChange property. public bool RepositionEditingControlOnValueChange { get { return false; } } // Implements the IDataGridViewEditingControl // .EditingControlDataGridView property. public DataGridView EditingControlDataGridView { get { return dataGridView; } set { dataGridView = value; } } // Implements the IDataGridViewEditingControl // .EditingControlValueChanged property. public bool EditingControlValueChanged { get { return valueChanged; } set { valuevalueChanged = value; } } // Implements the IDataGridViewEditingControl // .EditingPanelCursor property. public Cursor EditingPanelCursor { get { return base.Cursor; } } }
This is a just a start point. You may need to modify it to meet your actual requirement.If you have any question, please feel free to let me know.
- Marked As Answer byLinda LiuMSFT, ModeratorMonday, March 30, 2009 6:05 AM
- I am also trying to implement this...I have gotten the code you posted to work...sort of. I converted it to VB.NET...and I can get the checked listbox to display...but I want to be able to retrieve the selected items and cannot seem to figure that out. Any help would be appreciated. I am not binding the list...simply adding the list by hand.
Hey Jon, have you solved your problem with retrieving the items from the listbox.
Please share your converted VB.Net-Code.
Thanks and regards
Jan