Click here to Skip to main content
Licence CPOL
First Posted 17 Sep 2009
Views 67,013
Downloads 3,197
Bookmarked 118 times

Toggling the States of all CheckBoxes Inside a DataGridView Column

By | 2 Oct 2009 | Article
This article describes how to toggle the states of all CheckBoxes inside a particular DataGridView column.
 
Part of The SQL Zone sponsored by
See Also

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:

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:

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:

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.

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.

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:

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.

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.

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.

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.

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.

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.

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.

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.

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)

About the Author

Samir NIGAM

Team Leader

India India

Member

SAMIR NIGAM is a CodeProject MVP, a Microsoft Certified Technology
Specialist (MCTS)
as well as a Microsoft Certified Professional Developer (MCPD)
in C# for web-based applications. He is an insightful IT professional with
results-driven comprehensive technical skill having rich, hands-on work experience
in web-based applications using ASP.NET, C#, AJAX, Microsoft
Enterprise Library
, MS SQL Server 2005.
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, 3-Tier Architecture
and Algorithm Analysis & Design as well as good command over cross-browser
client side programming using JavaScript.
Awards:



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 PinmemberAbinash Bishoyi1:33 15 Apr '12  
QuestionProblem in clicking Row checkbox PinmemberMember 851748923:57 13 Mar '12  
AnswerRe: Problem in clicking Row checkbox Pinmemberchenandczh16:54 15 May '12  
GeneralMy vote of 5 PinmemberProEnggSoft19:20 29 Feb '12  
QuestionThanks! Pinmemberchirismirgh0:03 9 Aug '11  
AnswerRe: Thanks! PinmemberSamir NIGAM1:55 9 Aug '11  
GeneralThanks PingroupYZK22:45 29 Mar '11  
GeneralRe: Thanks PinmemberSamir NIGAM2:12 9 Aug '11  
Generalreal time attendance software Pinmemberdigvijay8122:52 6 Feb '11  
GeneralThanks for your dedication and helpfulness PinmemberSanjay4India9:11 2 Jan '11  
GeneralRe: Thanks for your dedication and helpfulness PinmemberSamir NIGAM2:00 9 Aug '11  
GeneralMy vote of 5 PinmemberSanjay4India9:04 2 Jan '11  
GeneralRe: My vote of 5 PinmemberSamir NIGAM2:04 9 Aug '11  
GeneralMy vote of 5 PinmemberGlimmerMan10:27 29 Dec '10  
GeneralRe: My vote of 5 PinmemberSamir NIGAM2:06 9 Aug '11  
GeneralMy vote of 5 PinmemberJunfengGuo14:41 5 Dec '10  
GeneralRe: My vote of 5 PinmemberSamir NIGAM2:07 9 Aug '11  
Generalgreat work Pinmembertcgcat3:05 10 Jun '10  
GeneralRe: great work PinmemberSamir NIGAM2:09 9 Aug '11  
GeneralGood Work! Pinmemberbbal197015:08 3 Dec '09  
GeneralRe: Good Work! PinmvpSamir NIGAM18:10 3 Dec '09  
GeneralNice work! PinmemberSushant Joshi4:25 21 Oct '09  
GeneralRe: Nice work! PinmvpSamir NIGAM20:49 21 Oct '09  
GeneralGood Stuff! PinmemberVicks12344:24 21 Oct '09  
GeneralRe: Good Stuff! PinmvpSamir NIGAM20:48 21 Oct '09  

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

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 2 Oct 2009
Article Copyright 2009 by Samir NIGAM
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid