Click here to Skip to main content
Click here to Skip to main content

Toggling the States of all CheckBoxes Inside a DataGridView Column

, 2 Oct 2009
Rate this:
Please Sign up or sign in to vote.
This article describes how to toggle the states of all CheckBoxes inside a particular DataGridView column.

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
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

 
GeneralMy vote of 3 Pinmembertomy xue9-Mar-14 5:25 
GeneralMy vote of 5 PinmemberAbinash Bishoyi15-Apr-12 1:33 
QuestionProblem in clicking Row checkbox PinmemberMember 851748913-Mar-12 23:57 
AnswerRe: Problem in clicking Row checkbox Pinmemberchenandczh15-May-12 16:54 
GeneralMy vote of 5 PinmemberProEnggSoft29-Feb-12 19:20 
QuestionThanks! Pinmemberchirismirgh9-Aug-11 0:03 
AnswerRe: Thanks! PinmemberSamir NIGAM9-Aug-11 1:55 
GeneralThanks PingroupYZK29-Mar-11 22:45 
GeneralRe: Thanks PinmemberSamir NIGAM9-Aug-11 2:12 
Generalreal time attendance software Pinmemberdigvijay816-Feb-11 22:52 
GeneralThanks for your dedication and helpfulness PinmemberSanjay4India2-Jan-11 9:11 
GeneralRe: Thanks for your dedication and helpfulness PinmemberSamir NIGAM9-Aug-11 2:00 
GeneralMy vote of 5 PinmemberSanjay4India2-Jan-11 9:04 
GeneralRe: My vote of 5 PinmemberSamir NIGAM9-Aug-11 2:04 
GeneralMy vote of 5 PinmemberGlimmerMan29-Dec-10 10:27 
GeneralRe: My vote of 5 PinmemberSamir NIGAM9-Aug-11 2:06 
GeneralMy vote of 5 PinmemberJunfengGuo5-Dec-10 14:41 
GeneralRe: My vote of 5 PinmemberSamir NIGAM9-Aug-11 2:07 
Generalgreat work Pinmembertcgcat10-Jun-10 3:05 
GeneralRe: great work PinmemberSamir NIGAM9-Aug-11 2:09 
GeneralGood Work! Pinmemberbbal19703-Dec-09 15:08 
GeneralRe: Good Work! PinmvpSamir NIGAM3-Dec-09 18:10 
GeneralNice work! PinmemberSushant Joshi21-Oct-09 4:25 
GeneralRe: Nice work! PinmvpSamir NIGAM21-Oct-09 20:49 
GeneralGood Stuff! PinmemberVicks123421-Oct-09 4:24 

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.

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 2 Oct 2009
Article Copyright 2009 by Samir NIGAM
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid