简体   繁体   English

更改Datagridview Checkbox Cell的checkBox Size并增加可点击区域

[英]Change checkBox Size of Datagridview Checkbox Cell and increase the clickable area

I have a checkbox column in my .net core Winform data GridVew.我的 .net 核心 Winform 数据 GridVew 中有一个复选框列。
I already made the checkbox bigger to be easier for the user to click.我已经使复选框更大,以便用户单击。

My code inside CellPainting ,我在CellPainting中的代码,

                e.PaintBackground(e.CellBounds, true);
                ControlPaint.DrawCheckBox(e.Graphics, e.CellBounds.X + 1, e.CellBounds.Y + 5,
                    e.CellBounds.Width - 10, e.CellBounds.Height - 10,
                    (bool)e.FormattedValue ? ButtonState.Checked : ButtonState.Normal);
                e.Handled = true;

Those are my reference links,这些是我的参考链接,
How to change checkBox Size in DatagridviewCheckboxCell 如何更改 DatagridviewCheckboxCell 中的复选框大小
Increase the size of Checkbox in #DataGridView in C# 增加C#中#DataGridView中Checkbox的大小

The result is like below,结果如下,

在此处输入图像描述

But the problem is the click area, even though the size of the checkbox is bigger, I realize the clickable area is still in its original size.但问题是点击区域,即使复选框的大小更大,我意识到可点击区域仍然是原来的大小。
As I show below, the green area is clickable area,如下所示,绿色区域是可点击区域,
在此处输入图像描述

I want to make the clickable area as big as the checkbox's size as show below,我想让可点击区域与复选框的大小一样大,如下所示,
在此处输入图像描述

Is there any solution?有什么解决办法吗?

When you mouse-click a DataGridViewCheckBoxCell to toggle the Checked state, you have to click on the content within the cell, clicking on elsewhere within the cell does not change a thing.当您用鼠标单击DataGridViewCheckBoxCell以切换选中的 state 时,您必须单击单元格内的内容,单击单元格内的其他位置不会改变任何事情。 The content of a DataGridViewCheckBoxCell is that small box area. DataGridViewCheckBoxCell的内容就是那个小框区域。 So, just drawing a bigger box does not resize or reposition (according to the column's DefaultCellStyle.Alignment ) that content area and it remains the same.因此,仅绘制一个更大的框不会调整该内容区域的大小或重新定位(根据该列的DefaultCellStyle.Alignment )并且它保持不变。 You need to code for that to tell, the content area has been clicked and the relevant base methods and events should be invoked.您需要为此编写代码来说明,内容区域已被单击,并且应该调用相关的基本方法和事件。

I'd create custom DataGridViewCheckBox column and cell to apply this requirement.我会创建自定义DataGridViewCheckBox列和单元格来应用此要求。

Within your project's namespace, derive a new class from DataGridViewCheckBoxColumn :在项目的命名空间中,从DataGridViewCheckBoxColumn派生一个新的 class :

public class CustomDataGridViewCheckBoxColumn : DataGridViewCheckBoxColumn
{
    public CustomDataGridViewCheckBoxColumn() : base() =>
        CellTemplate = new CustomDataGridViewCheckBoxCell();

    public override DataGridViewCell CellTemplate
    {
        get => base.CellTemplate;
        set
        {
            if (value != null &&
                !value.GetType().IsAssignableFrom(typeof(CustomDataGridViewCheckBoxCell)))
                throw new InvalidCastException("CustomDataGridViewCheckBoxCell.");

            base.CellTemplate = value;
        }
    }

    [Category("Appearance")]
    [DefaultValue(typeof(Size), "17, 17")]
    [Description("The size of the check box.")]
    public Size CheckBoxSize { get; set; } = new Size(17, 17);

    // We should copy the new properties.
    public override object Clone()
    {
        var c = base.Clone() as CustomDataGridViewCheckBoxColumn;
        c.CheckBoxSize = CheckBoxSize;
        return c;
    }
}

And another one derived from DataGridViewCheckBoxCell :另一个派生自DataGridViewCheckBoxCell

public class CustomDataGridViewCheckBoxCell : DataGridViewCheckBoxCell
{
    private Rectangle curCellBounds;
    private Rectangle checkBoxRect;

    public CustomDataGridViewCheckBoxCell() : base() { }

    protected override void Paint(
        Graphics g,
        Rectangle clipBounds,
        Rectangle cellBounds,
        int rowIndex,
        DataGridViewElementStates elementState,
        object value,
        object formattedValue,
        string errorText,
        DataGridViewCellStyle cellStyle,
        DataGridViewAdvancedBorderStyle advancedBorderStyle,
        DataGridViewPaintParts paintParts)
    {
        // Paint default except the check box parts.
        var parts = paintParts & ~(DataGridViewPaintParts.ContentForeground 
            | DataGridViewPaintParts.ContentBackground);

        base.Paint(g, 
            clipBounds, 
            cellBounds, 
            rowIndex, 
            elementState, 
            value, 
            formattedValue, 
            errorText, 
            cellStyle, 
            advancedBorderStyle, 
            parts);
            
        if (curCellBounds != cellBounds)
        {
            // To get the box size...
            var col = OwningColumn as CustomDataGridViewCheckBoxColumn;

            curCellBounds = cellBounds;
            // ToDo: Use col.DefaultCellStyle.Alignment or
            // DataGridView.ColumnHeadersDefaultCellStyle.Alignment
            // to position the box. MiddleCenter here...
            checkBoxRect = new Rectangle(
                (cellBounds.Width - col.CheckBoxSize.Width) / 2 + cellBounds.X,
                (cellBounds.Height - col.CheckBoxSize.Height) / 2 + cellBounds.Y,
                col.CheckBoxSize.Width,
                col.CheckBoxSize.Height);
        }

        ControlPaint.DrawCheckBox(g, checkBoxRect, (bool)formattedValue 
            ? ButtonState.Checked | ButtonState.Flat 
            : ButtonState.Flat);
    }

    // In case you don't use the `Alignment` property to position the 
    // box. This is to disallow toggling the state if you click on the
    // original content area outside the drawn box.
    protected override void OnContentClick(DataGridViewCellEventArgs e)
    {
        if (!ReadOnly &&
            checkBoxRect.Contains(DataGridView.PointToClient(Cursor.Position)))
            base.OnContentClick(e);
    }

    protected override void OnContentDoubleClick(DataGridViewCellEventArgs e)
    {
        if (!ReadOnly &&
            checkBoxRect.Contains(DataGridView.PointToClient(Cursor.Position)))
            base.OnContentDoubleClick(e);
    }

    // Toggle the checked state by mouse clicks...
    protected override void OnMouseUp(DataGridViewCellMouseEventArgs e)
    {
        base.OnMouseUp(e);

        if (!ReadOnly && e.Button == MouseButtons.Left &&
            checkBoxRect.Contains(DataGridView.PointToClient(Cursor.Position)))
        {
            Value = Value == null || !Convert.ToBoolean(Value);
            DataGridView.RefreshEdit();
            DataGridView.NotifyCurrentCellDirty(true);
        }    
    }

    // ... and Space key...
    protected override void OnKeyDown(KeyEventArgs e, int rowIndex)
    {
        base.OnKeyDown(e, rowIndex);
        if (!ReadOnly && e.KeyCode == Keys.Space)
        {
            Value = Value == null || !Convert.ToBoolean(Value.ToString());
            DataGridView.RefreshEdit();
            DataGridView.NotifyCurrentCellDirty(true);
        }
    }
}

Rebuild and check out the new column type in the grid's designer.在网格设计器中重建并检查新的列类型。

SO73550925A

In case you have a data-bound grid, set the AutoGenerateColumns property to false and add the columns manually.如果您有数据绑定网格,请将AutoGenerateColumns属性设置为false并手动添加列。 For example:例如:

private readonly static Random rnd = new Random();
//..

var dt = new DataTable();
dt.Columns.AddRange(new[]
{
    new DataColumn("Default", typeof(bool)),
    new DataColumn("Custom", typeof(bool))
});

for (int i = 1; i < 6; i++)
    dt.Rows.Add(rnd.Next(0, 2), rnd.Next(0, 2));

dataGridView1.AutoGenerateColumns = false;
dataGridView1.Columns.AddRange(new[]
{
    new DataGridViewCheckBoxColumn { HeaderText = "Default" },
    new CustomDataGridViewCheckBoxColumn 
    { 
        HeaderText = "Custom",
        CheckBoxSize = new Size(32, 32) 
    }
});
dataGridView1.DataSource = dt;

SO73550925B

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM