You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinForms DataGridViewButtonCell:阻止鼠标悬停与点击时背景色变更

解决DataGridView按钮单元格悬停/点击时变色的问题

问题描述

我创建了一个带有按钮列的DataGridView(简称dgv),需求是点击按钮单元格时将其颜色从绿色改为红色。但目前遇到两个问题:

  • 鼠标悬停在单元格上时,背景色变为透明(和网格背景色一致)
  • 点击单元格时会变成第三种颜色

已设置按钮的FlatStyle为Flat,且所有DefaultGridStyle颜色选项都设为绿色,需要阻止按钮单元格在鼠标悬停和点击时改变颜色。

我尝试过的代码

private void dgv_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)
{
   dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor;
}

private void dgv_CellMouseEnter(object sender, DataGridViewCellEventArgs e)
{
    dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = dgv.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor;
}

但选择其他颜色时,只会改变单元格边框颜色,背景色仍保持透明。


解决方案:自定义DataGridViewButtonCell

默认的DataGridViewButtonCell自带悬停、点击的内置样式逻辑,直接修改Style无法覆盖,必须通过自定义单元格类重写绘制逻辑来完全控制样式。

1. 创建自定义按钮单元格类

public class CustomDataGridViewButtonCell : DataGridViewButtonCell
{
    // 存储当前单元格的背景色,初始设为绿色
    private Color _backColor = Color.Green;

    public override Color BackColor
    {
        get => _backColor;
        set => _backColor = value;
    }

    protected override void Paint(Graphics graphics,
        Rectangle clipBounds, Rectangle cellBounds, int rowIndex,
        DataGridViewElementStates elementState, object value,
        object formattedValue, string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // 用自定义背景色填充整个单元格,覆盖默认样式
        using (Brush brush = new SolidBrush(_backColor))
        {
            graphics.FillRectangle(brush, cellBounds);
        }

        // 绘制按钮文本,保持居中对齐
        TextRenderer.DrawText(graphics, formattedValue.ToString(),
            cellStyle.Font, cellBounds, cellStyle.ForeColor,
            TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);

        // 绘制单元格边框(按需保留或删除)
        using (Pen pen = new Pen(cellStyle.ForeColor))
        {
            graphics.DrawRectangle(pen, cellBounds.Left, cellBounds.Top,
                cellBounds.Width - 1, cellBounds.Height - 1);
        }
    }
}

2. 创建自定义按钮列类

public class CustomDataGridViewButtonColumn : DataGridViewButtonColumn
{
    public CustomDataGridViewButtonColumn()
    {
        CellTemplate = new CustomDataGridViewButtonCell();
        FlatStyle = FlatStyle.Flat;
    }
}

3. 替换原有按钮列

如果是设计模式添加的默认按钮列,在窗体构造函数中替换:

public YourForm()
{
    InitializeComponent();
    // 移除原有默认按钮列(假设列名为buttonColumn1)
    dgv.Columns.Remove(buttonColumn1);
    
    // 添加自定义按钮列
    CustomDataGridViewButtonColumn customBtnCol = new CustomDataGridViewButtonColumn();
    customBtnCol.Name = "customButtonColumn";
    customBtnCol.HeaderText = "操作";
    customBtnCol.Text = "切换颜色";
    customBtnCol.UseColumnTextForButtonValue = true;
    dgv.Columns.Add(customBtnCol);
}

如果是动态创建列,直接使用CustomDataGridViewButtonColumn即可。

4. 处理点击事件切换颜色

在DataGridView的CellClick事件中修改单元格背景色:

private void dgv_CellClick(object sender, DataGridViewCellEventArgs e)
{
    // 确保点击的是自定义按钮列,且不是表头行
    if (e.ColumnIndex == dgv.Columns["customButtonColumn"].Index && e.RowIndex >= 0)
    {
        CustomDataGridViewButtonCell cell = (CustomDataGridViewButtonCell)dgv.Rows[e.RowIndex].Cells[e.ColumnIndex];
        // 切换绿色/红色
        cell.BackColor = cell.BackColor == Color.Green ? Color.Red : Color.Green;
        // 强制刷新单元格,立即显示新颜色
        dgv.InvalidateCell(e.ColumnIndex, e.RowIndex);
    }
}

为什么原有方法无效?

你之前的代码只是将BackColor赋值为自身当前值,没有任何实际修改;且默认DataGridViewButtonCell的悬停、点击样式是内部硬编码的逻辑,直接修改CellStyle无法覆盖这些内置行为,必须重写Paint方法完全接管绘制过程。

内容的提问来源于stack exchange,提问作者Francis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 20:37:29