Donate

Custom CheckedListBox DataGridView Column

Here's a working custom control class on how to embed CheckedListBox as a datagridview column. Source: Need a DataGridView Custom Column of Type ListView or CheckedListBox However, this class lacked functionalities such as obtaining the checked items and preserving the checked items during painting of the datagridview cell.
Here's the custom class:
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.ComponentModelTypeConverter valueTypeConverter, System.ComponentModelTypeConverter 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.DrawingGraphics graphics, System.DrawingRectangle clipBounds, System.DrawingRectangle 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;  
            }  
        }          
    } 
For the first requirement, I added a property to retrieve the checked items. Here's the property below:
public ICollection CheckedItems   
     {  
       get  
       {  
         if (internalControl == null)  
           return null;  
         else  
         {  
           if (internalControl != null)  
           {  
             if (internalControl.CheckedItems.Count > 0)  
             {  
               return internalControl.CheckedItems;  
             }  
             else  
             {  
               if ((CheckedListBox)this.DataGridView.Rows[RowIndex].Cells[ColumnIndex].DataGridView.EditingControl != null)  
               {  
                 CheckedListBox checks = (CheckedListBox)this.DataGridView.Rows[RowIndex].Cells[ColumnIndex].DataGridView.EditingControl;  
                 if (checks.CheckedItems.Count > 0)  
                   return checks.CheckedItems;  
                 else  
                   return null;  
               }  
               else  
                 return null;  
             }  
           }  
           else  
           {  
             return null;  
           }  
         }  
       }  
     }  
Here's how to get the checked items.
private void btnShow_Click(object sender, EventArgs e)  
     {  
       StringBuilder builder = new StringBuilder();  
       foreach (DataGridViewRow item in dgCheckListColumn1.Rows)  
       {  
         DataGridViewCell cell = item.Cells[1];  
         if (((cell as CheckedListBoxCell).CheckedItems != null))  
         {  
           if (((cell as CheckedListBoxCell).CheckedItems.Count > 0))  
           {  
             foreach (var checkItem in ((cell as CheckedListBoxCell).CheckedItems))  
             {  
               builder.AppendLine(String.Format("Row {0} : item: {1}", item.Index + 1, checkItem.ToString()));  
             }  
             builder.AppendLine(Environment.NewLine);  
           }   
         }  
       }  
       MessageBox.Show("Checked Items: \n" + builder.ToString());  
     } 
For the second requirement, it's a bit tricky. I have overriden the detaching control event in the datagridview cell and added a flag value for preserving the checked items during repainting of the objects.
See sample solution in codeproject: how to add checkedlistbox in datagridview column
Output
Custom CheckedListBox DataGridView Column
Cheers!

Comments

  1. How to Set the Collection of Items to the CheckedListBox in DataGridView?

    ReplyDelete
    Replies
    1. Hi, I haven't touched the code in years since 2014 since this has been sidetracked. I'll look for the project in our repository and will give feedback.

      Delete
  2. As far as I remember, you need to create a dummy model class that holds list of countries and Address.

    public class CountryAddressModel
    {
    public List Countries { get; set; }
    public string Address { get; set; }
    }

    In form load, create a list object with CountryAddressModel as type.
    List infoList = new List();
    * Populate the list with records
    * Then set the datagridview's datasource with the list
    dgCheckListColumn1.DataSource = infoList;

    Hope this helps.

    ReplyDelete
  3. Hi,
    Thank you very much for the code with information.
    Need one help, i have my condition and based on that how can I check the checkbox from code?

    ReplyDelete
    Replies
    1. Hi, its been a while since I've worked with this example. I advise you to please read the original source of this article. thanks

      Delete

Post a Comment

Donate

Popular Posts From This Blog

WPF CRUD Application Using DataGrid, MVVM Pattern, Entity Framework, And C#.NET

How To Insert Or Add Emojis In Microsoft Teams Status Message

Bootstrap Modal In ASP.NET MVC With CRUD Operations