DataGridView全选功能与滚动条定位 - (第五十讲)
这里给大家演示一种在WinForm环境下如何实现DataGridView的全选功能,以及重新定位滚动条位置,我们先来看下演示效果:

Form1.cs 代码如下:
using System;
using System.Windows.Forms;
namespace WindowsFormsApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
DatagridViewCheckBoxHeaderCell ch = new DatagridViewCheckBoxHeaderCell()
{
Value = "全选"
};
ch.OnCheckBoxClicked += Ch_OnCheckBoxClicked1;
dataGridView1.Columns[0].HeaderCell = ch;
// 初始化一些数据
for(int i = 0;i<20;i++)
{
int index = dataGridView1.Rows.Add();
dataGridView1.Rows[index].Cells[1].Value = i;
dataGridView1.Rows[index].Cells[2].Value = DateTime.Now;
}
}
private void Ch_OnCheckBoxClicked1(bool? state)
{
if (state != null)
{
// 结束编辑
dataGridView1.EndEdit();
// 控制勾选状态
foreach (DataGridViewRow row in dataGridView1.Rows)
{
row.Cells[0].Value = state;
}
}
}
/// <summary>
/// 定位滚动条到头部
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Top_Click(object sender, EventArgs e)
{
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows[0].Index;
}
/// <summary>
/// 定位滚动条到底部
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Button_Down_Click(object sender, EventArgs e)
{
dataGridView1.FirstDisplayedScrollingRowIndex = dataGridView1.Rows[dataGridView1.RowCount - 1].Index;
}
}
}
datagridviewCheckboxHeader.cs 代码如下:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp
{
/// <summary>
/// 复选框点击委托
/// </summary>
/// <param name="state">复选框状态</param>
public delegate void CheckBoxClickedHandler(bool? state);
/// <summary>
/// 点击复选框事件
/// </summary>
public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs
{
bool _bChecked;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="bChecked">复选框初始状态</param>
public DataGridViewCheckBoxHeaderCellEventArgs(bool bChecked)
{
_bChecked = bChecked;
}
/// <summary>
/// 复选框点击状态
/// </summary>
public bool Checked
{
get { return _bChecked; }
}
}
/// <summary>
/// 标头checkbox类
/// </summary>
class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
{
Point checkBoxLocation;
Size checkBoxSize;
bool? _checked = false;
Point _cellLocation = new Point();
System.Windows.Forms.VisualStyles.CheckBoxState _cbState =
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal;
/// <summary>
/// 鼠标点击事件
/// </summary>
public event CheckBoxClickedHandler OnCheckBoxClicked;
/// <summary>
/// 构造函数
/// </summary>
public DatagridViewCheckBoxHeaderCell()
{
}
/// <summary>
/// 获取复选框状态
/// </summary>
public bool? Checked
{
get => _checked;
set => _checked = value;
}
/// <summary>
/// 重写的Paint
/// </summary>
/// <param name="graphics">System.Drawing.Graphics 用于绘制单元格。</param>
/// <param name="clipBounds">一个 System.Drawing.Rectangle ,它表示的区域 System.Windows.Forms.DataGridView ,需要重新绘制。</param>
/// <param name="cellBounds">一个 System.Drawing.Rectangle ,其中包含正在绘制的单元格的边界。</param>
/// <param name="rowIndex">当前所绘制的单元格的行索引。</param>
/// <param name="dataGridViewElementState">按位组合 System.Windows.Forms.DataGridViewElementStates 值,该值指定单元格的状态。</param>
/// <param name="value">正在绘制的单元格的数据。</param>
/// <param name="formattedValue">正在绘制的单元格格式化的数据。</param>
/// <param name="errorText">与单元格关联的错误消息。</param>
/// <param name="cellStyle">一个 System.Windows.Forms.DataGridViewCellStyle 包含有关单元格的格式和样式信息。</param>
/// <param name="advancedBorderStyle">一个 System.Windows.Forms.DataGridViewAdvancedBorderStyle ,其中包含正在绘制的单元格的边框样式。</param>
/// <param name="paintParts">按位组合 System.Windows.Forms.DataGridViewPaintParts 值,该值指定需要绘制单元格的哪些部分。</param>
protected override void Paint(System.Drawing.Graphics graphics,
System.Drawing.Rectangle clipBounds,
System.Drawing.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);
Point p = new Point();
Size s = CheckBoxRenderer.GetGlyphSize(graphics,
System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal);
p.X = cellBounds.Location.X +
(cellBounds.Width / 2) - (s.Width / 2);
p.Y = cellBounds.Location.Y +
(cellBounds.Height / 2) - (s.Height / 2);
_cellLocation = cellBounds.Location;
checkBoxLocation = p;
checkBoxSize = s;
if (_checked == true)
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.CheckedNormal;
else if (_checked == false)
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.UncheckedNormal;
else if (_checked == null)
_cbState = System.Windows.Forms.VisualStyles.
CheckBoxState.MixedNormal;
CheckBoxRenderer.DrawCheckBox
(graphics, checkBoxLocation, _cbState);
}
/// <summary>
/// 鼠标点击事件
/// </summary>
/// <param name="e">事件数据</param>
protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
{
Point p = new Point(e.X + _cellLocation.X, e.Y + _cellLocation.Y);
if (p.X >= checkBoxLocation.X && p.X <=
checkBoxLocation.X + checkBoxSize.Width
&& p.Y >= checkBoxLocation.Y && p.Y <=
checkBoxLocation.Y + checkBoxSize.Height)
{
switch (_checked)
{
case true:
_checked = false;
break;
case false:
_checked = true;
break;
case null:
_checked = true;
break;
default:
break;
}
if (OnCheckBoxClicked != null)
{
OnCheckBoxClicked(_checked);
this.DataGridView.InvalidateCell(this);
}
}
base.OnMouseClick(e);
}
}
}