Sunday, 2 August 2015

Create a select all checkbox column Header in DataGridView Winforms

In this post we are going to see how to create a checkbox header column in the datagridview to get a feature like select all option in Datagridview.

First we have to understand some few basics things, normally gridviewcolumn header seems like empty, if we want something display in header then we have to customize it.Here we take a simple example like showing a employee details where we want to select all employee records in single click.

To Achieve this we have to do following steps.
1. Drag and Drop a DataGridView from Toolbox.
2. Create a First column as CheckBox 
3. Then bind the data with the DataGridView.

            DataGridViewCheckBoxColumn col1 = new DataGridViewCheckBoxColumn();           
            dataGridView1.Columns.Add(col1);

            dataGridView1.Rows.Add(4);

            dataGridView1.DataSource = new List<Employee>() {
            new Employee(){ FirstName = "Rajesh",LastName = "G",Id=1},
            new Employee(){ FirstName = "Suresh",LastName="G",Id=2}
            };
            

After this step if we run the application, it looks like following one.



Now actually we need to have an Header of a First column should be checkbox, and when select the checkbox it should trigger an event is the requirement.

We have to add a template for HeaderCell for the first column.So create a class which is derived from the DataGridViewColumnHeaderCell, now we can start implement our logic


1. Our header must have a default value with uncheck.
2. It should be present in the center
3. We have to create a checkbox in header.
4. Create a custom event.
4. Create a Event for mouse click.
5. check whether is click above the checkbox, if so trigger the event

    public class CheckBoxHeaderCellEventArgs:EventArgs
    {
        private bool _isChecked;
        public bool IsChecked {
            get { return _isChecked; }
        }

        public CheckBoxHeaderCellEventArgs(bool _checked)
        {
            _isChecked = _checked;

        }

    }




  public delegate void CheckBoxHeaderClickHandler(CheckBoxHeaderCellEventArgs e);

    class CheckBoxHeaderCell:DataGridViewColumnHeaderCell
    {
        Size checkboxsize;
        bool ischecked;
        Point location;
        Point cellboundsLocation;
        CheckBoxState state = CheckBoxState.UncheckedNormal;

        public event CheckBoxHeaderClickHandler OnCheckBoxHeaderClick;

        public CheckBoxHeaderCell()
        {
            location = new Point();
            cellboundsLocation = new Point();
            ischecked = false;
        }
      
        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
         /* Make a condition to check whether the click is fired inside a checkbox region */
            Point clickpoint = new Point(e.X + cellboundsLocation.X, e.Y +                                                  cellboundsLocation.Y);

            if ( (clickpoint.X > location.X && clickpoint.X < (location.X +                                       checkboxsize.Width)) && (clickpoint.Y > location.Y && clickpoint.Y <                         (location.Y+checkboxsize.Height)))
            {
                ischecked = !ischecked;
                if (OnCheckBoxHeaderClick != null)
                {
                    OnCheckBoxHeaderClick(new CheckBoxHeaderCellEventArgs(ischecked));
                    this.DataGridView.InvalidateCell(this);
                }
            }
            base.OnMouseClick(e);
        }

        protected override void Paint(Graphics graphics, Rectangle clipBounds, 
             Rectangle cellBounds, int rowIndex, DataGridViewElementStates                                 dataGridViewElementState,object value, object formattedValue, string errorText, 
            DataGridViewCellStyle cellStyle,DataGridViewAdvancedBorderStyle     
            advancedBorderStyle, DataGridViewPaintParts paintParts)
        {
           
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, 
           value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);

            checkboxsize = CheckBoxRenderer.GetGlyphSize(graphics,                                                               CheckBoxState.UncheckedNormal);
            location.X = cellBounds.X + (cellBounds.Width/2 - checkboxsize.Width/2);
            location.Y = cellBounds.Y + (cellBounds.Height/2 - checkboxsize.Height/2);
            cellboundsLocation = cellBounds.Location;
          
            if (ischecked)
                state = CheckBoxState.CheckedNormal;
            else
                state = CheckBoxState.UncheckedNormal;

            CheckBoxRenderer.DrawCheckBox(graphics, location, state);


        }
    } 


After that  assign the cell template to the gridview column like this.

            DataGridViewCheckBoxColumn col1 = new DataGridViewCheckBoxColumn();
            var checkheader = new CheckBoxHeaderCell();
            checkheader.OnCheckBoxHeaderClick += checkheader_OnCheckBoxHeaderClick;
            col1.HeaderCell = checkheader;
           
            dataGridView1.Columns.Add(col1);

            dataGridView1.Rows.Add(4);

            dataGridView1.DataSource = new List<Employee>() {
            new Employee(){ FirstName = "Rajesh",LastName = "G",Id=1},
            new Employee(){ FirstName = "Suresh",LastName="G",Id=2}
            };

             

When ever click the header check box it will trigger an event , we already hooked an handler for that

        void checkheader_OnCheckBoxHeaderClick(CheckBoxHeaderCellEventArgs e)
        {
            dataGridView1.BeginEdit(true);
            foreach (DataGridViewRow item in dataGridView1.Rows)
            {
                item.Cells[0].Value = e.IsChecked;               
            }
            dataGridView1.EndEdit();

        } 

We can see the exact output what we required.
Output:


From this we can learn how to create a column with checkbox as a header in DataGridView winforms.

No comments:

Post a Comment