為DataGridView 新增複選框,實現全選功能
阿新 • • 發佈:2019-01-30
1、指定DataGridView的第一列為DataGridViewCheckBoxColumn
2、為第一列的標題欄新增一個CheckBox,假設為HeaderCheckBox
同時為HeaderCheckBox定義好 MouseClick 和 KeyUp 事件
private void frmSelectAll_Load(object sender, EventArgs e) { … AddHeaderCheckBox(); HeaderCheckBox.KeyUp += new KeyEventHandler(HeaderCheckBox_KeyUp); HeaderCheckBox.MouseClick += new MouseEventHandler(HeaderCheckBox_MouseClick); … } private void AddHeaderCheckBox() { HeaderCheckBox = new CheckBox(); HeaderCheckBox.Size = new Size(15, 15); //Add the CheckBox into the DataGridView this.dgvSelectAll.Controls.Add(HeaderCheckBox); } private void HeaderCheckBox_MouseClick(object sender, MouseEventArgs e) { HeaderCheckBoxClick((CheckBox)sender); } private void HeaderCheckBox_KeyUp(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.Space) HeaderCheckBoxClick((CheckBox)sender); } private void HeaderCheckBoxClick(CheckBox HCheckBox) { IsHeaderCheckBoxClicked = true; foreach (DataGridViewRow Row in dgvSelectAll.Rows) ((DataGridViewCheckBoxCell)Row.Cells[0]).Value = HCheckBox.Checked; dgvSelectAll.RefreshEdit(); TotalCheckedCheckBoxes = HCheckBox.Checked ? TotalCheckBoxes : 0; IsHeaderCheckBoxClicked = false; }
3、以上程式碼發現HeaderCheckBox不在正確的位置顯示
所以新增繪製程式碼,調整位置
private void frmSelectAll_Load(object sender, EventArgs e) { ... dgvSelectAll.CellPainting += new DataGridViewCellPaintingEventHandler(dgvSelectAll_CellPainting); ... } private void dgvSelectAll_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) { if (e.RowIndex == -1 && e.ColumnIndex == 0) ResetHeaderCheckBoxLocation(e.ColumnIndex, e.RowIndex); } private void ResetHeaderCheckBoxLocation(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; }
4、到此為止,第一列的顯示,全選/全不選功能已經做好
此時,如果DataGridView的ReadOnly為True,則發現點選CheckBox,無法修改其選中狀態
而設定ReadOnly為false,則發現可以修改CheckBox的狀態,但是DataGridView處於編輯狀態
private void frmSelectAll_Load(object sender, EventArgs e) { ... dgvSelectAll.CurrentCellDirtyStateChanged += new EventHandler(dgvSelectAll_CurrentCellDirtyStateChanged); ... } private void dgvSelectAll_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvSelectAll.CurrentCell is DataGridViewCheckBoxCell) dgvSelectAll.CommitEdit(DataGridViewDataErrorContexts.Commit); }
注意:如果僅希望第一列可以修改,其他列不能修改,可以把其他列設定為只讀
5、 單擊HeaderCheckBox,讓DataGridView處於全選狀態
然後取消部分記錄的選中狀態,此時HeaderCheckBox仍然為選中狀態,而不是預期中的非選中狀態
private void frmSelectAll_Load(object sender, EventArgs e)
{
...
dgvSelectAll.CellValueChanged += new DataGridViewCellEventHandler(dgvSelectAll_CellValueChanged);
...
}
private void dgvSelectAll_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (!IsHeaderCheckBoxClicked)
RowCheckBoxClick((DataGridViewCheckBoxCell)dgvSelectAll[e.ColumnIndex, e.RowIndex]);
}
private void RowCheckBoxClick(DataGridViewCheckBoxCell RCheckBox)
{
if (RCheckBox != null)
{
//Modifiy 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;
}
}
6、IsHeaderCheckBoxClicked的作用因為HeaderCheckBox狀態的改變,會觸發DataGridView的CellValueChanged事件
而DataGridView的CellValueChanged事件也會導致HeaderCheckBox狀態修改
所以,這裡用了一個全域性變數,來避免程式進入死迴圈