如何将Checkbox作为dataGridView的ColumnHeader

Syn*_*ter 10 c# visual-studio

我正在用C#VS2005开发一个窗口应用程序.我有一个dataGridView,其中第一列有Checkboxes.现在我希望Column标题也是一个CheckBox,如果我选择列中的所有Checkboxex应该被选中.我怎样才能做到这一点.?我参考了Code Project链接

但如果我使用它,如果我点击FirstCell(而不是标题),所有下面的单元格都会被选中.但我想在Column标题中使用CheckBox.我怎样才能做到这一点.?

Zac*_*son 12

我还需要CheckBox在列的列标题中有一个DataGridView.我是这样做的:

  • 创建一个继承自的类 DataGridViewColumnHeaderCell
  • 在内部使用a System.Windows.Forms.CheckBox来存储已检查状态并提供OS样式的可视化CheckBox表示.
  • 使用a Bitmap作为缓冲区并CheckBox在其上绘制常规(使用CheckBox.DrawToBitmap)
  • DataGridViewColumnHeaderCell.Paint在将缓冲区绘制到Graphics提供者之前,覆盖并在必要时更新缓冲区Paint
  • 提供派生的Checked属性DataGridViewColumnHeaderCell,以及CheckedChanged事件
  • DataGridViewColumnHeaderCell在填充HeaderCell时替换列中的派生DataGridView.
  • 选中并取消选中CheckBox单击列标题的时间,仅当鼠标单击位于其范围内时CheckBox
  • 通过监听CheckedChanged事件,更新底层数据对象然后调用ResetBindings更新来实现派生类之外的check-all/uncheck-allDataGridView

这是我写的类,它来自DataGridViewColumnHeaderCell:

class DataGridViewCheckBoxColumnHeaderCell : DataGridViewColumnHeaderCell
{
    private Bitmap buffer;
    private CheckBox checkBox;
    private Rectangle checkBoxBounds;

    public DataGridViewCheckBoxColumnHeaderCell()
    {
        this.checkBox = new CheckBox();
    }

    public event EventHandler CheckedChanged;

    public bool Checked
    {
        get 
        { 
            return this.checkBox.Checked; 
        }

        set
        {
            if (!this.Checked == value)
            {
                this.checkBox.Checked = value;
                if (this.buffer != null)
                {
                    this.buffer.Dispose();
                    this.buffer = null;
                }

                this.OnCheckedChanged(EventArgs.Empty);

                if (this.DataGridView != null)
                {
                    this.DataGridView.Refresh();
                }
            }
        }
    }

    protected override void Paint(
        Graphics graphics, 
        Rectangle clipBounds, 
        Rectangle cellBounds, 
        int rowIndex, 
        DataGridViewElementStates dataGridViewElementState, 
        object value, 
        object formattedValue, 
        string errorText, 
        DataGridViewCellStyle cellStyle, 
        DataGridViewAdvancedBorderStyle advancedBorderStyle, 
        DataGridViewPaintParts paintParts)
    {
        // Passing String.Empty in place of 
        // value and formattedValue prevents 
        // this header cell from having text.

        base.Paint(
            graphics, 
            clipBounds, 
            cellBounds, 
            rowIndex, 
            dataGridViewElementState, 
            String.Empty, 
            String.Empty, 
            errorText, 
            cellStyle, 
            advancedBorderStyle, 
            paintParts);

        if (this.buffer == null 
            || cellBounds.Width != this.buffer.Width
            || cellBounds.Height != this.buffer.Height)
        {
            this.UpdateBuffer(cellBounds.Size);
        }

        graphics.DrawImage(this.buffer, cellBounds.Location);
    }

    protected override Size GetPreferredSize(
        Graphics graphics, 
        DataGridViewCellStyle cellStyle, 
        int rowIndex, 
        Size constraintSize)
    {
        return this.checkBox.GetPreferredSize(constraintSize);
    }

    protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left 
            && this.checkBoxBounds.Contains(e.Location))
        {
            this.Checked = !this.Checked;
        }

        base.OnMouseClick(e);
    }

    private void UpdateBuffer(Size size)
    {
        Bitmap updatedBuffer = new Bitmap(size.Width, size.Height);

        this.checkBox.Size = size;

        if (this.checkBox.Size.Width > 0 && this.checkBox.Size.Height > 0)
        {
            Bitmap renderedCheckbox = new Bitmap(
                this.checkBox.Width, 
                this.checkBox.Height);

            this.checkBox.DrawToBitmap(
                renderedCheckbox, 
                new Rectangle(new Point(), this.checkBox.Size));

            MakeTransparent(renderedCheckbox, this.checkBox.BackColor);
            Bitmap croppedRenderedCheckbox = AutoCrop(
                renderedCheckbox, 
                Color.Transparent);

            // TODO implement alignment, right now it is always
            // MiddleCenter regardless of this.Style.Alignment

            this.checkBox.Location = new Point(
                (updatedBuffer.Width - croppedRenderedCheckbox.Width) / 2, 
                (updatedBuffer.Height - croppedRenderedCheckbox.Height) / 2);

            Graphics updatedBufferGraphics = Graphics.FromImage(updatedBuffer);
            updatedBufferGraphics.DrawImage(
                croppedRenderedCheckbox, 
                this.checkBox.Location);

            this.checkBoxBounds = new Rectangle(
                this.checkBox.Location, 
                croppedRenderedCheckbox.Size);

            renderedCheckbox.Dispose();
            croppedRenderedCheckbox.Dispose();
        }

        if (this.buffer != null)
        {
            this.buffer.Dispose();
        }

        this.buffer = updatedBuffer;
    }

    protected virtual void OnCheckedChanged(EventArgs e)
    {
        EventHandler handler = this.CheckedChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

    // The methods below are helper methods for manipulating Bitmaps

    private static void MakeTransparent(Bitmap bitmap, Color transparencyMask)
    {
        int transparencyMaskArgb = transparencyMask.ToArgb();
        int transparentArgb = Color.Transparent.ToArgb();

        List deadColumns = new List();

        for (int x = 0; x = 0; x--)
        {
            if (deadColumns.Count == bitmap.Height)
            {
                break;
            }

            for (int y = bitmap.Height - 1; y >= 0; y--)
            {
                if (deadColumns.Contains(y))
                {
                    continue;
                }

                int pixel = bitmap.GetPixel(x, y).ToArgb();

                if (pixel == transparencyMaskArgb)
                {
                    bitmap.SetPixel(x, y, Color.Transparent);
                }
                else if (pixel != transparentArgb)
                {
                    deadColumns.Add(y);
                    break;
                }
            }
        }
    }

    public static Bitmap AutoCrop(Bitmap bitmap, Color backgroundColor)
    {
        Size croppedSize = bitmap.Size;
        Point cropOrigin = new Point();
        int backgroundColorToArgb = backgroundColor.ToArgb();

        for (int x = bitmap.Width - 1; x >= 0; x--)
        {
            bool allPixelsAreBackgroundColor = true;
            for (int y = bitmap.Height - 1; y >= 0; y--)
            {
                if (bitmap.GetPixel(x, y).ToArgb() != backgroundColorToArgb)
                {
                    allPixelsAreBackgroundColor = false;
                    break;
                }
            }

            if (allPixelsAreBackgroundColor)
            {
                croppedSize.Width--;
            }
            else
            {
                break;
            }
        }

        for (int y = bitmap.Height - 1; y >= 0; y--)
        {
            bool allPixelsAreBackgroundColor = true;
            for (int x = bitmap.Width - 1; x >= 0; x--)
            {
                if (bitmap.GetPixel(x, y).ToArgb() != backgroundColorToArgb)
                {
                    allPixelsAreBackgroundColor = false;
                    break;
                }
            }

            if (allPixelsAreBackgroundColor)
            {
                croppedSize.Height--;
            }
            else
            {
                break;
            }
        }

        for (int x = 0; x = 0 && xWhole = 0)
                {
                    bitmapSection.SetPixel(x, y, bitmap.GetPixel(xWhole, yWhole));
                }
                else
                {
                    bitmapSection.SetPixel(x, y, Color.Transparent);
                }
            }
        }

        return bitmapSection;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ehs*_*san 11

上面的解决方案有点好,但也有一种更简单的方法!只需添加这两种方法,然后就可以得到你想要的!

首先show_chkBox在代码中添加一个方法,然后在onload表单的函数中或在创建之后调用它DataGridView:

 private void show_chkBox()
 {
     Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true);
     // set checkbox header to center of header cell. +1 pixel to position 
     rect.Y = 3;
     rect.X = rect.Location.X + (rect.Width/4);
     CheckBox checkboxHeader = new CheckBox();
     checkboxHeader.Name = "checkboxHeader";
     //datagridview[0, 0].ToolTipText = "sdfsdf";
     checkboxHeader.Size = new Size(18, 18);
     checkboxHeader.Location = rect.Location;
     checkboxHeader.CheckedChanged += new EventHandler(checkboxHeader_CheckedChanged);
     dataGridView1.Controls.Add(checkboxHeader);
 }
Run Code Online (Sandbox Code Playgroud)

然后你会在标题中有复选框.

对于选择问题,只需添加以下代码:

private void checkboxHeader_CheckedChanged(object sender, EventArgs e)
{             
    CheckBox headerBox = ((CheckBox)dataGridView1.Controls.Find("checkboxHeader", true)[0]);
    int index = 0;
    for (int i = 0; i < dataGridView1.RowCount; i++)
    {
        dataGridView1.Rows[i].Cells[0].Value = headerBox.Checked;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 把this.dataGridView1.EndEdit(); 在for循环结束之后 (2认同)