Click here to Skip to main content
15,867,686 members
Articles / Desktop Programming / Windows Forms

Toggling the States of all CheckBoxes Inside a DataGridView Column

Rate me:
Please Sign up or sign in to vote.
4.96/5 (71 votes)
2 Oct 2009CPOL5 min read 307.7K   20.2K   161   48
This article describes how to toggle the states of all CheckBoxes inside a particular DataGridView column.
Image 1

Table of Contents

Introduction

More than a year and a half ago, I wrote an article, Selecting/ Deselecting all the CheckBoxes Inside a GridView for Web Forms. Last month, I got a chance to implement the same functionality for the DataGridView control for Windows Forms. Initially, I thought it would be as easy as in the case of the GridView for Web Forms, but it wasn't. It is a bit tricky in the case of the DataGridView control for Windows Forms. E.g., adding a header CheckBox in a column of the DataGridView control is not a straightforward job. So after doing a lot of research work and spending a lot of time on studying the functionality of the control, I have finally arrived at the following solution. All modifications and clarifications are most welcome!

Adding Row CheckBoxes in a DataGridView Column

To add row CheckBoxes in a DataGridView column, I've added a DataGridViewCheckBoxColumn column control. I've also made the AllowUserToAddRows and AllowUserToDeleteRows properties of the DataGridView [dgvSelectAll] equal to false, as:

C#
dgvSelectAll.AllowUserToAddRows = false;
dgvSelectAll.AllowUserToDeleteRows = false; 

Adding a Header CheckBox in a DataGridView Column

As I said earlier, adding a header CheckBox in a DataGridView column is a bit tricky. I've added a header CheckBox [HeaderCheckBox] in a DataGridView column by invoking the AddHeaderCheckBox method through the Windows Form’s Load event, as:

C#
private void frmSelectAll_Load(object sender, EventArgs e)
{
   AddHeaderCheckBox();
   …
}

I'll explain the AddHeaderCheckBox method later.

Attaching the Header CheckBox’s MouseClick and KeyUp Events

I've wired up the header CheckBox’s MouseClick and KeyUp events through the Windows Form’s Load event, as:

C#
private void frmSelectAll_Load(object sender, EventArgs e) 
{
   … 
   HeaderCheckBox.KeyUp += new KeyEventHandler(HeaderCheckBox_KeyUp);
   HeaderCheckBox.MouseClick += new MouseEventHandler(HeaderCheckBox_MouseClick);
   … 
}

Header CheckBox’s MouseClick Event Handler

The MouseClick event gets fired whenever we click on the header CheckBox. Here, the HeaderCheckBoxClick method is invoked by passing the header CheckBox’s reference as an argument. I'll discuss the HeaderCheckBoxClick method later.

C#
private void HeaderCheckBox_MouseClick(object sender, MouseEventArgs e) 
{
    HeaderCheckBoxClick((CheckBox)sender); 
}

Header CheckBox’s KeyUp Event Handler

The KeyUp event gets fired whenever we release a key from the header CheckBox if it has focus. Here also, the HeaderCheckBoxClick method is invoked by passing the header CheckBox’s reference as an argument, provided this event is raised by the space bar.

C#
private void HeaderCheckBox_KeyUp(object sender, KeyEventArgs e)
{
    if(e.KeyCode == Keys.Space)
       HeaderCheckBoxClick((CheckBox)sender);
}

Attaching the DataGridView’s CellValueChanged, CurrentCellDirtyStateChanged and CellPainting Events

I've wired up the DataGridView’s CellValueChanged, CurrentCellDirtyStateChanged, and CellPainting events, respectively, through the Windows Form’s Load event, as:

C#
private void frmSelectAll_Load(object sender, EventArgs e)
{
   ...

   dgvSelectAll.CellValueChanged += 
     new DataGridViewCellEventHandler(dgvSelectAll_CellValueChanged);
   dgvSelectAll.CurrentCellDirtyStateChanged += 
     new EventHandler(dgvSelectAll_CurrentCellDirtyStateChanged);
   dgvSelectAll.CellPainting += 
     new DataGridViewCellPaintingEventHandler(dgvSelectAll_CellPainting);
   
   ...
}

DataGridView’s CellValueChanged Event Handler

The CellValueChanged event gets fired whenever the value of a DataGridView cell is changed. Here, the RowCheckBoxClick method is invoked by passing a reference of DataGridViewCheckBoxCell that raised this event, provided the header CheckBox isn't clicked. I'll describe the RowCheckBoxClick method later.

C#
private void dgvSelectAll_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
   if (!IsHeaderCheckBoxClicked)
      RowCheckBoxClick((DataGridViewCheckBoxCell)dgvSelectAll[e.ColumnIndex, e.RowIndex]);
}

DataGridView’s CellPainting Event Handler

The CellPainting event gets fired whenever a DataGridView cell needs to be drawn. Basically, I've handled this event to reset the position of the header CheckBox inside the DataGridView whenever it is required. Here, first it is ensured that the cell to be drawn is the header of the first column; then, the ResetHeaderCheckBoxLocation method is invoked by passing e.ColumnIndex and e.RowIndex as arguments. I'll discuss the details of the ResetHeaderCheckBoxLocation method later.

C#
private void dgvSelectAll_CellPainting(object sender, 
             DataGridViewCellPaintingEventArgs e)
{
   if (e.RowIndex == -1 && e.ColumnIndex == 0)
      ResetHeaderCheckBoxLocation(e.ColumnIndex, e.RowIndex);
}

DataGridView’s CurrentCellDirtyStateChanged Event Handler

The CurrentCellDirtyStateChanged event gets fired whenever the state of a DataGridView cell changes in relation to a change in its contents. Basically, this event calls the CommitEdit method to raise the CellValueChanged event and determine the current value of a DataGridViewCheckBoxCell.

C#
private void dgvSelectAll_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
    if (dgvSelectAll.CurrentCell is DataGridViewCheckBoxCell)
       dgvSelectAll.CommitEdit(DataGridViewDataErrorContexts.Commit);
}

AddHeaderCheckBox Method

The AddHeaderCheckBox method is used to add a header CheckBox control in the DataGridView control. Basically, this method doesn't add a CheckBox control in a particular DataGridView column; it simply adds a header CheckBox control in the DataGridView. This is the job of the ResetLocation method.

C#
private void AddHeaderCheckBox()
{
    HeaderCheckBox = new CheckBox();

    HeaderCheckBox.Size = new Size(15, 15);

    //Add the CheckBox into the DataGridView
    this.dgvSelectAll.Controls.Add(HeaderCheckBox);
}

ResetLocation Method

This method is responsible for setting the header CheckBox location in a particular DataGridView column. In this method, first, I get cell boundaries of a particular header cell, and then calculate the coordinates for the header CheckBox in order to change the location to make it stay on the header of a particular DataGridview column. Finally, I set the location of the header CheckBox in the DataGridview.

C#
private void ResetLocation(int ColumnIndex, int RowIndex)
{
   //Get the column header cell bounds
   Rectangle oRectangle = 
     this.dgvSelectAll.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);

   Point oPoint = new Point();


   oPoint.X = oRectangle.Location.X + (oRectangle.Width - HeaderCheckBox.Width) / 2 + 1;
   oPoint.Y = oRectangle.Location.Y + (oRectangle.Height - HeaderCheckBox.Height) / 2 + 1;

   //Change the location of the CheckBox to make it stay on the header
   HeaderCheckBox.Location = oPoint;
}

HeaderCheckBoxClick Method

This method is used to toggle the state of all row CheckBoxes of a particular DataGridView column depending on the header CheckBox’s state. Before starting this process, I make the global variable IsHeaderCheckBoxClicked equal to false indicating that the state of the row CheckBoxes is just going to be toggled. Each time the state of a row CheckBox is changed, the DataGridView’s CellValueChanged event is fired. In this event, the RowCheckBoxClick method is invoked if the value of IsHeaderCheckBoxClicked is found to be false. Now, after toggling the row CheckBoxes' states, I call the DataGridView’s RefreshEdit method in order to refresh the value of the current cell with the underlying cell value when the cell is in edit mode, discarding any previous value. Next, the value of the global variable TotalCheckedCheckBoxes is set as per the header CheckBox’s state. Finally, I revert back the value of the global variable IsHeaderCheckBoxClicked.

C#
private void HeaderCheckBoxClick(CheckBox HCheckBox)
{
   IsHeaderCheckBoxClicked = true;

   foreach (DataGridViewRow Row in dgvSelectAll.Rows)
      ((DataGridViewCheckBoxCell)Row.Cells["chkBxSelect"]).Value = HCheckBox.Checked;

   dgvSelectAll.RefreshEdit();

   TotalCheckedCheckBoxes = HCheckBox.Checked ? TotalCheckBoxes : 0;

   IsHeaderCheckBoxClicked = false;
}

RowCheckBoxClick Method

This method checks / unchecks the header CheckBox’s state depending upon whether all CheckBoxes of a DataGridView column are checked or unchecked.

C#
private void RowCheckBoxClick(DataGridViewCheckBoxCell RCheckBox)
{
   if (RCheckBox != null)
   {
      //Modify Counter;            
      if ((bool)RCheckBox.Value && TotalCheckedCheckBoxes < TotalCheckBoxes)
         TotalCheckedCheckBoxes++;
      else if (TotalCheckedCheckBoxes > 0)
         TotalCheckedCheckBoxes--;

      //Change state of the header CheckBox.
      if (TotalCheckedCheckBoxes < TotalCheckBoxes)
         HeaderCheckBox.Checked = false;
      else if (TotalCheckedCheckBoxes == TotalCheckBoxes)
         HeaderCheckBox.Checked = true;
   }
}

BindGridView Method

This method is used to bind the DataGridView as well as to initialize the global variables TotalCheckBoxes and TotalCheckedCheckBoxes.

C#
private void BindGridView()
{
   dgvSelectAll.DataSource = GetDataSource();

   TotalCheckBoxes = dgvSelectAll.RowCount;
   TotalCheckedCheckBoxes = 0;
}

Winding Up

This is the path that I've adopted to implement this functionality. If anyone has a different idea or suggestion to improve this functionality further, share it with me. I've created and tested this demo application on a machine having VS 2008 and Win XP SP3.

History

  • 1st October, 2009 -- Article updated (Modified Introduction section)
  • 25th September, 2009 -- Article updated (Added table of contents)
  • 18th September, 2009 -- Original version posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Infogain India Pvt Ltd
India India


Samir NIGAM is a Microsoft Certified Professional. He is an insightful IT professional with results-driven comprehensive technical skill having rich, hands-on work experience n web-based applications using ASP.NET, C#, AJAX, Web Service, WCF, jQuery, Microsoft Enterprise Library , LINQ, MS Entity Framework, nHibernate, MS SQL Server & SSRS.



He has earned his master degree (MCA) from U.P. Technical University, Lucknow, INDIA, his post graduate dipoma (PGDCA ) from Institute of Engineering and Rural Technology, Allahabad, INDIA and his bachelor degree (BSc - Mathematics) from University of Allahabad, Allahabad, INDIA.



He has good knowledge of Object Oriented Programming, n-Tier Architecture, SOLID Principle, and Algorithm Analysis & Design as well as good command over cross-browser client side programming using JavaScript & jQuery,.



Awards:



Comments and Discussions

 
QuestionPersist the existing datagridcheckbox value on click of listbox selectedindex change. Pin
Abhishek Kumar18-Oct-18 22:42
Abhishek Kumar18-Oct-18 22:42 
Questionhow to make datagridview contents uneditable Pin
Member 1257364118-Sep-16 10:30
Member 1257364118-Sep-16 10:30 
QuestionResetHeaderCheckBoxLocation(e.ColumnIndex, e.RowIndex); Pin
Member 115244359-Jan-16 1:24
Member 115244359-Jan-16 1:24 
GeneralThat is a good example Pin
jash.liao29-Nov-15 16:59
jash.liao29-Nov-15 16:59 
QuestionToggle Select all then deselect other boxes Pin
Rencyrence5-Nov-15 20:11
Rencyrence5-Nov-15 20:11 
GeneralExcellent Pin
Anthony DiFranco7-Jan-15 7:04
Anthony DiFranco7-Jan-15 7:04 
QuestionHow do i loop through the checked rows, get the values, and remove it from the datatable and datagrid Pin
Uwakpeter11-Aug-14 3:01
professionalUwakpeter11-Aug-14 3:01 
QuestionThank You Pin
suman198329-Jul-14 5:18
suman198329-Jul-14 5:18 
Thank You It helped me a lot...Saved my time.
AnswerRe: Thank You Pin
Samir NIGAM29-Jul-14 19:03
Samir NIGAM29-Jul-14 19:03 
GeneralMy vote of 3 Pin
tomy xue9-Mar-14 5:25
tomy xue9-Mar-14 5:25 
GeneralMy vote of 5 Pin
Abinash Bishoyi15-Apr-12 1:33
Abinash Bishoyi15-Apr-12 1:33 
QuestionProblem in clicking Row checkbox Pin
Member 851748913-Mar-12 23:57
Member 851748913-Mar-12 23:57 
AnswerRe: Problem in clicking Row checkbox Pin
chenandczh15-May-12 16:54
chenandczh15-May-12 16:54 
GeneralMy vote of 5 Pin
ProEnggSoft29-Feb-12 19:20
ProEnggSoft29-Feb-12 19:20 
QuestionThanks! Pin
chirismirgh9-Aug-11 0:03
chirismirgh9-Aug-11 0:03 
AnswerRe: Thanks! Pin
Samir NIGAM9-Aug-11 1:55
Samir NIGAM9-Aug-11 1:55 
GeneralThanks Pin
YZK29-Mar-11 22:45
YZK29-Mar-11 22:45 
GeneralRe: Thanks Pin
Samir NIGAM9-Aug-11 2:12
Samir NIGAM9-Aug-11 2:12 
Generalreal time attendance software Pin
digvijay816-Feb-11 22:52
digvijay816-Feb-11 22:52 
GeneralThanks for your dedication and helpfulness Pin
Sanjay4India2-Jan-11 9:11
Sanjay4India2-Jan-11 9:11 
GeneralRe: Thanks for your dedication and helpfulness Pin
Samir NIGAM9-Aug-11 2:00
Samir NIGAM9-Aug-11 2:00 
GeneralMy vote of 5 Pin
Sanjay4India2-Jan-11 9:04
Sanjay4India2-Jan-11 9:04 
GeneralRe: My vote of 5 Pin
Samir NIGAM9-Aug-11 2:04
Samir NIGAM9-Aug-11 2:04 
GeneralMy vote of 5 Pin
karenpayne29-Dec-10 10:27
karenpayne29-Dec-10 10:27 
GeneralRe: My vote of 5 Pin
Samir NIGAM9-Aug-11 2:06
Samir NIGAM9-Aug-11 2:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.