任何列中DataGridView标题中的复选框

12

实际上我已经解决了在DGV头部拥有复选框的问题,这里是代码:

Rectangle rect = dataGridView1.GetCellDisplayRectangle(0, -1, true);
        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);    

实际上,我向我的DGV添加了一列DataGridViewCheckBoxColumn,然后在表单的加载中添加了上面的代码。我的问题是,如您所见,对于第一列它运行得很好,因为我可以在代码中设置该列的rect.X,但是对于通知者列怎么办,由于日志列可以通过最大化和这些东西进行更改,我如何在程序上知道此列标题的位置。

enter image description here 最后,例如,我如何在程序上知道列[3]的标题位置…… 提前致谢。


1
我对你的问题非常困惑。看起来你已经解决了标题中提出的问题... - Cody Gray
主要问题是如何检索datagridview中单元格的位置或位置,并考虑到某些列(例如“日志”)可能处于Autosize = Fill模式! - Ehsan
10个回答

21

试试这个

#region GridViewCheckBoxColumn


    [System.Drawing.ToolboxBitmap(typeof(System.Windows.Forms.DataGridViewCheckBoxColumn))]
    public class GridViewCheckBoxColumn : DataGridViewCheckBoxColumn
    {
        #region Constructor

        public GridViewCheckBoxColumn()
        {
            DatagridViewCheckBoxHeaderCell datagridViewCheckBoxHeaderCell = new DatagridViewCheckBoxHeaderCell();

            this.HeaderCell = datagridViewCheckBoxHeaderCell;
            this.Width = 50;

            //this.DataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.grvList_CellFormatting);
            datagridViewCheckBoxHeaderCell.OnCheckBoxClicked += new CheckBoxClickedHandler(datagridViewCheckBoxHeaderCell_OnCheckBoxClicked);

        }

        #endregion

        #region Methods

        void datagridViewCheckBoxHeaderCell_OnCheckBoxClicked(int columnIndex, bool state)
        {
            DataGridView.RefreshEdit();

            foreach (DataGridViewRow row in this.DataGridView.Rows)
            {
                if (!row.Cells[columnIndex].ReadOnly)
                {
                    row.Cells[columnIndex].Value = state;
                }
            }
            DataGridView.RefreshEdit();
        }



        #endregion
    }

    #endregion

    #region DatagridViewCheckBoxHeaderCell

    public delegate void CheckBoxClickedHandler(int columnIndex, bool state);
    public class DataGridViewCheckBoxHeaderCellEventArgs : EventArgs
    {
        bool _bChecked;
        public DataGridViewCheckBoxHeaderCellEventArgs(int columnIndex, bool bChecked)
        {
            _bChecked = bChecked;
        }
        public bool Checked
        {
            get { return _bChecked; }
        }
    }
    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;
        public event CheckBoxClickedHandler OnCheckBoxClicked;

        public DatagridViewCheckBoxHeaderCell()
        {
        }

        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)
                _cbState = System.Windows.Forms.VisualStyles.
                CheckBoxState.CheckedNormal;
            else
                _cbState = System.Windows.Forms.VisualStyles.
                CheckBoxState.UncheckedNormal;
            CheckBoxRenderer.DrawCheckBox
            (graphics, checkBoxLocation, _cbState);
        }

        protected override void OnMouseClick(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)
            {
                _checked = !_checked;
                if (OnCheckBoxClicked != null)
                {
                    OnCheckBoxClicked(e.ColumnIndex, _checked);
                    this.DataGridView.InvalidateCell(this);
                }
            }
            base.OnMouseClick(e);
        }

    }

    #endregion

    #region ColumnSelection

    class DataGridViewColumnSelector
    {
        // the DataGridView to which the DataGridViewColumnSelector is attached
        private DataGridView mDataGridView = null;
        // a CheckedListBox containing the column header text and checkboxes
        private CheckedListBox mCheckedListBox;
        // a ToolStripDropDown object used to show the popup
        private ToolStripDropDown mPopup;

        /// <summary>
        /// The max height of the popup
        /// </summary>
        public int MaxHeight = 300;
        /// <summary>
        /// The width of the popup
        /// </summary>
        public int Width = 200;

        /// <summary>
        /// Gets or sets the DataGridView to which the DataGridViewColumnSelector is attached
        /// </summary>
        public DataGridView DataGridView
        {
            get { return mDataGridView; }
            set
            {
                // If any, remove handler from current DataGridView 
                if (mDataGridView != null) mDataGridView.CellMouseClick -= new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
                // Set the new DataGridView
                mDataGridView = value;
                // Attach CellMouseClick handler to DataGridView
                if (mDataGridView != null) mDataGridView.CellMouseClick += new DataGridViewCellMouseEventHandler(mDataGridView_CellMouseClick);
            }
        }

        // When user right-clicks the cell origin, it clears and fill the CheckedListBox with
        // columns header text. Then it shows the popup. 
        // In this way the CheckedListBox items are always refreshed to reflect changes occurred in 
        // DataGridView columns (column additions or name changes and so on).
        void mDataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right && e.RowIndex == -1 && e.ColumnIndex == 0)
            {
                mCheckedListBox.Items.Clear();
                foreach (DataGridViewColumn c in mDataGridView.Columns)
                {
                    mCheckedListBox.Items.Add(c.HeaderText, c.Visible);
                }                
                int PreferredHeight = (mCheckedListBox.Items.Count * 16) + 7;
                mCheckedListBox.Height = (PreferredHeight < MaxHeight) ? PreferredHeight : MaxHeight;
                mCheckedListBox.Width = this.Width;
                mPopup.Show(mDataGridView.PointToScreen(new Point(e.X, e.Y)));
            }
        }

        // The constructor creates an instance of CheckedListBox and ToolStripDropDown.
        // the CheckedListBox is hosted by ToolStripControlHost, which in turn is
        // added to ToolStripDropDown.
        public DataGridViewColumnSelector()
        {
            mCheckedListBox = new CheckedListBox();
            mCheckedListBox.CheckOnClick = true;
            mCheckedListBox.ItemCheck += new ItemCheckEventHandler(mCheckedListBox_ItemCheck);

            ToolStripControlHost mControlHost = new ToolStripControlHost(mCheckedListBox);
            mControlHost.Padding = Padding.Empty;
            mControlHost.Margin = Padding.Empty;
            mControlHost.AutoSize = false;

            mPopup = new ToolStripDropDown();
            mPopup.Padding = Padding.Empty;
            mPopup.Items.Add(mControlHost);
        }

        public DataGridViewColumnSelector(DataGridView dgv)
            : this()
        {
            this.DataGridView = dgv;
        }

        // When user checks / unchecks a checkbox, the related column visibility is 
        // switched.
        void mCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            mDataGridView.Columns[e.Index].Visible = (e.NewValue == CheckState.Checked);
        }
    }

    #endregion

好的,这很好,但是当我想为通知列添加复选框标题时,我该如何知道其位置并定义转到该列!:( - Ehsan
请问这段代码具体是做什么的,我该如何将其用于我的目的?谢谢。 - Ehsan
将此作为组件类添加,然后添加类型为GridViewCheckBoxColumn的列,您可以看到它正在工作。 - Nighil
@Nighil 如果所有复选框都被选中,则标题不会自动选中,反之亦然;这个方法并不完全有效。 - Trikaldarshiii

7
这个解决方案对我很有用,它将复选框添加到标题单元格中。您只需实现“全选”方法和可能的“列调整大小”方法(以在中心替换复选框)。
// Creating checkbox without panel
CheckBox checkbox = new CheckBox();
checkbox.Size = new System.Drawing.Size(15, 15);
checkbox.BackColor = Color.Transparent;

// Reset properties
checkbox.Padding = new Padding(0);
checkbox.Margin = new Padding(0);
checkbox.Text = "";

// Add checkbox to datagrid cell
myDataGrid.Controls.Add(checkbox);
DataGridViewHeaderCell header = myDataGrid.Columns[myColumnWithCheckboxes.Index].HeaderCell;
checkbox.Location = new Point(
    header.ContentBounds.Left + (header.ContentBounds.Right - header.ContentBounds.Left + checkbox.Size.Width) / 2,
    header.ContentBounds.Top + (header.ContentBounds.Bottom - header.ContentBounds.Top + checkbox.Size.Height) / 2
);

3

对我而言,最干净的解决方案来自"56ka",这是我对它的升级。借此,您保留了按排序方向排序、在复选框旁边添加标签、正常复选框和所有相关功能的能力。基于.NET Framework 4.0制作,适用于DataTable和EF。

public static void AddSelectorColumn(this DataGridView dgv, int width = 50, string columnName = "Selected", Action<DataGridViewColumn> addHeaderCheckBoxOverride = null)
{
    if (dgv.Columns[columnName] == null)
    {
        var dt = dgv.Table();

        var dcol = new DataColumn(columnName, typeof(bool));
        dt.Columns.Add(dcol);

        dt.ColumnChanged += (s, e) =>
        {
            var chCols = e.Row.GetChangedColumns();
            if (chCols.Count == 1 && chCols[0].Equals(dcol))
                e.Row.AcceptChanges();
        };
    }

    var col = dgv.Columns[columnName];
    col.HeaderText = "";
    col.ReadOnly = false;
    col.DisplayIndex = 0;
    if (addHeaderCheckBoxOverride != null)
        addHeaderCheckBoxOverride(col);
    else
        col.AddHeaderCheckBox();
    col.Width = width;
}

public static CheckBox AddHeaderCheckBox(this DataGridViewColumn column, HorizontalAlignment align = HorizontalAlignment.Center, int leftBorderOffset = 0, int rightBorderOffset = 0, Func<object, bool> getValue = null, Action<object, bool> setValue = null)
{
    if (column.DataGridView == null) throw new ArgumentNullException("First you need to add the column to grid.");

    // Creating checkbox without panel
    CheckBox checkbox = new CheckBox();
    checkbox.Name = "chk" + column.Name;
    checkbox.Size = new Size(15, 15);
    checkbox.BackColor = Color.Transparent;
    checkbox.Enabled = !column.ReadOnly;

    // Reset properties
    checkbox.Padding = new Padding(0);
    checkbox.Margin = new Padding(0);
    checkbox.Text = "";

    var changedByUser = true;
    var dgv = column.DataGridView;

    checkbox.CheckedChanged += (s, e) =>
    {
        if (changedByUser)
        {
            try
            {
                changedByUser = false;

                if (dgv.IsCurrentCellInEditMode && dgv.CurrentCell.OwningColumn.Name.Equals(column.Name))
                    dgv.EndEdit();

                var dgvRows = new List<DataGridViewRow>((dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows).Cast<DataGridViewRow>());

                if (column.IsDataBound)
                {
                    //adding to list because of BindingSource sort by that column
                    var boundItems = new List<object>();
                    var areDataRows = dgvRows.Count < 1 || dgvRows[0].DataBoundItem is DataRowView;
                    if (areDataRows)
                    {
                        foreach (DataGridViewRow row in dgvRows)
                            boundItems.Add(((DataRowView)row.DataBoundItem).Row);
                        foreach (DataRow dr in boundItems)
                        {
                            var val = dr[column.DataPropertyName];
                            if ((val is bool && (bool)val) != checkbox.Checked)
                                dr[column.DataPropertyName] = checkbox.Checked;
                        }
                    }
                    else
                    {
                        foreach (DataGridViewRow row in dgvRows)
                            boundItems.Add(row.DataBoundItem);
                        foreach (var item in boundItems)
                        {
                            var val = getValue(item);
                            if (val != checkbox.Checked)
                                setValue(item, checkbox.Checked);
                        }
                    }
                }
                else
                {
                    foreach (DataGridViewRow dgr in dgvRows)
                    {
                        var cell = dgr.Cells[column.Name];
                        if ((cell.Value is bool && (bool)cell.Value) != checkbox.Checked)
                            cell.Value = checkbox.Checked;
                    }
                }
            }
            finally
            {
                changedByUser = true;
            }
        }
    };

    // Add checkbox to datagrid cell
    dgv.Controls.Add(checkbox);

    Action onColResize = () =>
    {
        var colCheck = dgv.Columns[column.Name];
        if (colCheck == null) return;
        int colLeft = (dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0) - (colCheck.Frozen ? 0 : dgv.HorizontalScrollingOffset);
        foreach (DataGridViewColumn col in dgv.Columns)
        {
            if (col.DisplayIndex >= colCheck.DisplayIndex) break;
            if (!col.Visible) continue;
            colLeft += col.Width;
        }

        var newPoint = new Point(colLeft, dgv.ColumnHeadersHeight / 2 - checkbox.Height / 2);

        if (align == HorizontalAlignment.Left)
            newPoint.X += 3;
        else if (align == HorizontalAlignment.Center)
            newPoint.X += colCheck.Width / 2 - checkbox.Width / 2;
        else if (align == HorizontalAlignment.Right)
            newPoint.X += colCheck.Width - checkbox.Width - 3;

        var minLeft = colLeft + leftBorderOffset;
        var maxLeft = colLeft + colCheck.Width - checkbox.Width + rightBorderOffset;

        if (newPoint.X < minLeft) newPoint.X = minLeft;
        if (newPoint.X > maxLeft) newPoint.X = maxLeft;

        checkbox.Location = newPoint;
        checkbox.Visible = colCheck.Visible;
    };
    dgv.ColumnWidthChanged += (s, e) => onColResize();
    dgv.ColumnHeadersHeightChanged += (s, e) => onColResize();
    dgv.Scroll += (s, e) => onColResize();
    dgv.Resize += (s, e) => onColResize();
    dgv.Sorted += (s, e) => onColResize();
    dgv.RowHeadersWidthChanged += (s, e) => onColResize();
    dgv.ColumnStateChanged += (s, e) => onColResize();

    Action<object> onDataChanged = (e) =>
    {
        if (!changedByUser) return;
        if (e is DataColumnChangeEventArgs)
        {
            if (!((DataColumnChangeEventArgs)e).Column.ColumnName.Equals(column.Name))
                return;
        }
        else if (e is ListChangedEventArgs)
        {
            var prop = ((ListChangedEventArgs)e).PropertyDescriptor;
            if (prop != null && !prop.Name.Equals(column.DataPropertyName))
                return;
        }

        bool allAreTrue = true;
        foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows)
        {
            var val = row.Cells[column.Name].Value;
            if (!(val is bool) || !(bool)val)
            {
                allAreTrue = false;
                break;
            }
        }

        try
        {
            changedByUser = false;
            var tag = checkbox.Tag;
            checkbox.Tag = "AUTO";
            try
            {
                checkbox.Checked = allAreTrue;
            }
            finally { checkbox.Tag = tag; }
        }
        finally
        {
            changedByUser = true;
        }
    };
    dgv.SelectionChanged += (s, e) => onDataChanged(e);
    if (dgv.DataSource is BindingSource)
        ((BindingSource)dgv.DataSource).ListChanged += (s, e) => onDataChanged(e);
    else if (dgv.DataSource is DataSet)
        ((DataSet)dgv.DataSource).Tables[dgv.DataMember].ColumnChanged += (s, e) => onDataChanged(e);
    else if (dgv.DataSource is DataTable)
        ((DataTable)dgv.DataSource).ColumnChanged += (s, e) => onDataChanged(e);

    return checkbox;
}

2

对于我来说,56ka的答案非常完美。 我只是修正了位置(2px)。

    private CheckBox ColumnCheckbox(DataGridView dataGridView)
    {
        CheckBox checkBox = new CheckBox();
        checkBox.Size = new Size(15, 15);
        checkBox.BackColor = Color.Transparent;

        // Reset properties
        checkBox.Padding = new Padding(0);
        checkBox.Margin = new Padding(0);
        checkBox.Text = "";

        // Add checkbox to datagrid cell
        dataGridView.Controls.Add(checkBox);
        DataGridViewHeaderCell header = dataGridView.Columns[0].HeaderCell;
        checkBox.Location = new Point(
            (header.ContentBounds.Left +
             (header.ContentBounds.Right - header.ContentBounds.Left + checkBox.Size.Width)
             /2) - 2,
            (header.ContentBounds.Top +
             (header.ContentBounds.Bottom - header.ContentBounds.Top + checkBox.Size.Height)
             /2) - 2);
        return checkBox;
    }

1
public class DataGridViewEx : DataGridView
{
    Dictionary<DataGridViewColumn, bool> dictionaryCheckBox = new Dictionary<DataGridViewColumn, bool>();

    System.Drawing.Bitmap[] bmCheckBox = new System.Drawing.Bitmap[2];

    bool executarValueChanged = true;

    public DataGridViewEx()
        : base()
    {
        #region CheckBox no header da coluna

        CheckBox chkTemp = new CheckBox();

        chkTemp.AutoSize = true;
        chkTemp.BackColor = System.Drawing.Color.Transparent;
        chkTemp.Size = new System.Drawing.Size(16, 16);
        chkTemp.UseVisualStyleBackColor = false;

        bmCheckBox[0] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);
        bmCheckBox[1] = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);

        chkTemp.Checked = false;
        chkTemp.DrawToBitmap(bmCheckBox[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

        chkTemp.Checked = true;
        chkTemp.DrawToBitmap(bmCheckBox[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

        #endregion
    }

    public void CheckBoxHeader(DataGridViewCheckBoxColumn column, bool enabled)
    {
        if (enabled == true)
        {
            if (dictionaryCheckBox.Any(f => f.Key == column) == false)
            {
                dictionaryCheckBox.Add(column, false);
                this.InvalidateCell(column.HeaderCell);
            }
        }
        else
        {
            dictionaryCheckBox.Remove(column);

            this.InvalidateCell(column.HeaderCell);
        }
    }

    protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
    {
        base.OnCellPainting(e);

        if (e.ColumnIndex >= 0 && e.RowIndex == -1 && dictionaryCheckBox.Any(f => f.Key == this.Columns[e.ColumnIndex]) == true)
        {
            Bitmap bmp = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0];

            Rectangle imageBounds = new Rectangle(new Point(e.CellBounds.Location.X + (e.CellBounds.Width / 2) - (bmp.Size.Width / 2), e.CellBounds.Location.Y + (e.CellBounds.Height / 2) - (bmp.Size.Height / 2)), bmp.Size);

            e.PaintBackground(e.CellBounds, true);
            e.PaintContent(e.CellBounds);
            e.Graphics.DrawImage(bmp, imageBounds);
            e.Handled = true;
        }
    }

    protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
    {
        base.OnColumnHeaderMouseClick(e);

        if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true)
        {
            var header = this.Columns[e.ColumnIndex].HeaderCell;
            Bitmap img = dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true ? bmCheckBox[1] : bmCheckBox[0];

            if (e.Button == System.Windows.Forms.MouseButtons.Left &&
               e.Y >= header.ContentBounds.Y + (header.Size.Height / 2) - (img.Height / 2) &&
               e.Y <= header.ContentBounds.Y + (header.Size.Height / 2) + (img.Height / 2) &&
               e.X >= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) - (img.Width / 2) &&
               e.X <= header.ContentBounds.X + (this.Columns[e.ColumnIndex].Width / 2) + (img.Width / 2))
            {
                dictionaryCheckBox[this.Columns[e.ColumnIndex]] = !dictionaryCheckBox[this.Columns[e.ColumnIndex]];

                this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);

                executarValueChanged = false;
                for (Int32 i = 0; i < this.Rows.Count; i++)
                {
                    this.Rows[i].Cells[e.ColumnIndex].Value = dictionaryCheckBox[this.Columns[e.ColumnIndex]];
                    this.RefreshEdit();
                }
                executarValueChanged = true;
            }

        }
    }

    protected override void OnRowsAdded(DataGridViewRowsAddedEventArgs e)
    {
        base.OnRowsAdded(e);

        List<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList();
        foreach (DataGridViewColumn coluna in listColunas)
        {
            if (dictionaryCheckBox.ContainsKey(coluna) == true)
            {
                if (dictionaryCheckBox[coluna] == true)
                {
                    executarValueChanged = false;

                    this.Rows[e.RowIndex].Cells[coluna.Index].Value = true;
                    this.RefreshEdit();

                    executarValueChanged = true;
                }
            }
        }
    }

    protected override void OnRowsRemoved(DataGridViewRowsRemovedEventArgs e)
    {
        base.OnRowsRemoved(e);

        List<DataGridViewColumn> listColunas = this.Columns.Cast<DataGridViewColumn>().Where(f => f.GetType() == typeof(DataGridViewCheckBoxColumn)).ToList();
        foreach (DataGridViewColumn coluna in listColunas)
        {
            if (dictionaryCheckBox.ContainsKey(coluna) == true)
            {
                if (this.Rows.Count == 0)
                {
                    dictionaryCheckBox[coluna] = false;
                    this.InvalidateCell(coluna.HeaderCell);
                }
                else
                {
                    Int32 numeroLinhas = this.Rows.Cast<DataGridViewRow>().Where(f => Convert.ToBoolean(f.Cells[coluna.Index].Value) == true).Count();
                    if (numeroLinhas == this.Rows.Count)
                    {
                        dictionaryCheckBox[coluna] = true;
                        this.InvalidateCell(coluna.HeaderCell);
                    }
                }
            }
        }
    }

    protected override void OnCellValueChanged(DataGridViewCellEventArgs e)
    {
        base.OnCellValueChanged(e);

        if (e.ColumnIndex >= 0 && e.RowIndex >= 0)
        {
            if (dictionaryCheckBox.ContainsKey(this.Columns[e.ColumnIndex]) == true)
            {
                if (executarValueChanged == false)
                {
                    return;
                }

                Boolean existeFalse = this.Rows.Cast<DataGridViewRow>().Any(f => Convert.ToBoolean(f.Cells[e.ColumnIndex].Value) == false);

                if (existeFalse == true)
                {
                    if (dictionaryCheckBox[this.Columns[e.ColumnIndex]] == true)
                    {
                        dictionaryCheckBox[this.Columns[e.ColumnIndex]] = false;
                        this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);
                    }
                }
                else
                {
                    dictionaryCheckBox[this.Columns[e.ColumnIndex]] = true;
                    this.InvalidateCell(this.Columns[e.ColumnIndex].HeaderCell);
                }
            }
        }
    }

    protected override void OnCurrentCellDirtyStateChanged(EventArgs e)
    {
        base.OnCurrentCellDirtyStateChanged(e);

        if (this.CurrentCell is DataGridViewCheckBoxCell)
        {
            this.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }
}

使用:

dataGridViewEx1.CheckBoxHeader(dataGridViewEx1.Columns[0] as DataGridViewCheckBoxColumn, true);


1

您需要调用列上的点击事件。 通过识别您点击的列,您可以访问所需的行并更改相应字段的值。 例如:

    private void dataGridViewOrderState_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == dataGridViewOrderState.Columns["selectedDataGridViewCheckBoxColumn"].Index)
        {
            var bid = dataGridViewOrderState.Rows[e.RowIndex];
            var selectedRow = (OrderStateLocal)bid.DataBoundItem;
            if (selectedRow == null)
                return;
            selectedRow.Selected = !selectedRow.Selected;
        }

    }

1
    private void AddHeaderCheckbox()
    {
        CheckBox cb = new CheckBox();
        // your checkbox size
        cb.Size = new Size(15, 15);

        // datagridview checkbox header column cell size
        var cell = dgv.Columns[0].HeaderCell.Size;

        // calculate location
        cb.Location = new Point((cell.Width - cb.Size.Width) / 2, (cell.Height - cb.Size.Height) / 2);

        dgv.Controls.Add(cb);
    }

0
当您删除一个列并在相同的索引位置添加另一个列时,可能会遗漏一些内容。
在AddHeaderCheckBox函数中添加以下内容。
 Action onColRemoved = () =>
 {
     checkbox.Dispose();
 };
 dgv.ColumnRemoved += (s, e) => onColRemoved();

并修改这个:

foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection) dgv.Rows : dgv.SelectedRows)
{ 
    var val = row.Cells[column.Name].Value;
    if (!(val is bool) || !(bool) val)
    {
        allAreTrue = false;
        break;
    }
}

转换为


foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection) dgv.Rows : dgv.SelectedRows)
{
    if (dgv.Columns.Contains(column.Name))
    {
        var val = row.Cells[column.Name].Value;
        if (!(val is bool) || !(bool) val)
        {
            allAreTrue = false;
            break;
        }
    }
}

0

我使用了dataGridView_CellPainting事件。

在该事件中,我加入了一个条件语句来设置复选框在标题单元格内的位置 - 例如第1列第0行。

CellBounds有许多属性可用于设置位置。我取了单元格的右侧“e.CellBounds.Right”,然后减去复选框的宽度,将复选框放置在标题单元格的右下角。

void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
    {
    if (e.ColumnIndex == 1 && e.RowIndex == 0) 
       {
        TopCheckBox.Left = e.CellBounds.Right - 15;
       }
    }

-1

这是同一个问题的另一种解决方案。你所需要做的就是像下面显示的那样调用构造函数。

new ColocarHeaderCheckBox(dataGridView1, colActivo.Index);

问候。

using System;
using System.Drawing;
using System.Windows.Forms;

namespace Util
{
    public class ColocarHeaderCheckBox
    {
        CheckBox headerCheckBox = new CheckBox();
        int columnIndex = 0;
        DataGridView dgv;

        /// <summary>
        /// Coloca un CheckBox en el Header del Datagriview para seleccionar o 
        /// deseleccionar todas las filas a la vez.
        /// </summary>
        /// <param name="dgv"></param>
        /// <param name="columnIndex"></param>

        /// (2022-08-29) Editado por Kong Fan
        /// TODO 
        /// Falta hacer que el cuadro de checkbox pueda cambiar de tamano
        public ColocarHeaderCheckBox(DataGridView dgv, int columnIndex)
        {
            // *** Asegurarse de que sea posible utilizar el HeaderCheckBox
            if (!dgv.ColumnHeadersVisible) return;
            if (!dgv.Columns[columnIndex].Visible) return;
            if (dgv.Columns[columnIndex].CellType != typeof(DataGridViewCheckBoxCell)) return;
            // *** Recibir parámetros
            this.columnIndex = columnIndex;
            this.dgv = dgv;
            // *** Crear el HeaderCheckBox y enlazar eventos
            CrearCheckBox();
            // *** Muestra el estado inicial del HeaderCheckBox
            CambiarEstadoHeaderCheckBox(this.dgv);
            // *** Evento para controlar el scroll horizontal
            dgv.Scroll += new ScrollEventHandler(Dgv_Scrolled);
        }

        private void Dgv_Scrolled(object sender, ScrollEventArgs e)
        {
            if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
            {
                // *** Si se mueve el scroll vuelve a crear el control
                dgv.Controls.Remove(headerCheckBox);
                if (!CrearCheckBox()) dgv.Controls.Remove(headerCheckBox);
            }
        }

        private bool CrearCheckBox()
        {
            int anchoCuadro = 14;
            int altoCuadro = 14;
            int anchoCelda = dgv.Columns[columnIndex].Width;
            int altoCelda = dgv.ColumnHeadersHeight;
            // *** Determinar la ubicación de la esquina superior izquierda de las columnas adyacentes
            Point columnaUbicacion = dgv.GetColumnDisplayRectangle(columnIndex, true).Location;
            Point columnaAntesUbicacion = new Point();
            Point columnaDespuesUbicacion = new Point();
            // *** Tomar ubicaciones de columnas antes y despues de la columna designada
            bool tieneAntes = false;
            bool tieneDespues = false;
            for (int i = 0; i < dgv.Columns.Count; i++)
            {
                if (dgv.Columns[i].Visible && i < columnIndex && !tieneAntes)
                {
                    columnaAntesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
                    tieneAntes = true;
                }
                if (dgv.Columns[i].Visible && i > columnIndex && !tieneDespues)
                {
                    columnaDespuesUbicacion = dgv.GetColumnDisplayRectangle(i, true).Location;
                    tieneDespues = true;
                }
            }
            // *** Comprobar si hay espacio para crear el control
            if ((columnaDespuesUbicacion.X - columnaUbicacion.X) < (anchoCelda + anchoCuadro) / 2
                    && dgv.FirstDisplayedScrollingColumnIndex != columnIndex)
                return false;
            if ((dgv.Width - columnaAntesUbicacion.X) < ((anchoCelda + anchoCuadro) / 2))
                return false;
            // *** Centrar la posición del headerCheckBox y el alto de la casilla
            int posicionX = 0;
            if (columnaDespuesUbicacion.X != 0)
                posicionX = columnaDespuesUbicacion.X - (anchoCelda + anchoCuadro) / 2;
            else
                posicionX = columnaUbicacion.X + (anchoCelda - anchoCuadro) / 2;
            if (altoCelda < (altoCuadro - 1)) altoCuadro = altoCelda - 2;
            int posicionY = (altoCelda - altoCuadro) / 2 + 1;
            // *** Agregar el control a la DataGridView
            headerCheckBox.Location = new Point(posicionX, posicionY);
            headerCheckBox.BackColor = Color.White;
            headerCheckBox.Size = new Size(anchoCuadro, altoCuadro);
            headerCheckBox.ThreeState = true;
            dgv.Controls.Add(headerCheckBox);
            //  *** Asignar evento Click al headerCheckBox
            headerCheckBox.Click += new EventHandler(HeaderCheckBox_Clicked);
            //  *** Asignar evento Click a las casillas de datos del DataGridView
            dgv.CellContentClick += new DataGridViewCellEventHandler(DataGridView_CellClick);
            return true;
        }

        private void HeaderCheckBox_Clicked(object sender, EventArgs e)
        {
            // *** Extraer del parámetro el sender.Parent la DataGriView
            DataGridView dgv = (DataGridView)((CheckBox)sender).Parent;
            // *** Necesario para finalizar cualquier edición                                                              
            dgv.EndEdit();
            // *** Recorrer todas las filas de la columna para checkar todos o ninguno
            foreach (DataGridViewRow row in dgv.Rows)
            {
                if (headerCheckBox.CheckState == CheckState.Checked)
                {
                    (row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = true;
                    headerCheckBox.Checked = true;
                }
                else
                {
                    (row.Cells[columnIndex] as DataGridViewCheckBoxCell).Value = false;
                    headerCheckBox.Checked = false;
                }
            }
        }

        private void DataGridView_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView dgv = sender as DataGridView;
            // *** Comprobar si está haciendo Click en la fila correcta
            if (e.RowIndex >= 0 && e.ColumnIndex == columnIndex)
                // *** Cambiar el estado del headerCheckBox
                CambiarEstadoHeaderCheckBox(dgv);
        }

        private void CambiarEstadoHeaderCheckBox(DataGridView dgv)
        {
            int positivos = 0;
            int negativos = 0;
            int totalFilas = dgv.RowCount;
            int contador = 0;
            // *** Recorrer todas las filas y determinar uno de los 3 estados del headerCheckBox
            foreach (DataGridViewRow fila in dgv.Rows)
            {
                contador++;
                if ((bool)fila.Cells[columnIndex].EditedFormattedValue == true)
                {
                    positivos++;
                }
                if ((bool)fila.Cells[columnIndex].EditedFormattedValue == false)
                {
                    negativos++;
                }
            }
            if (totalFilas == contador)
            {
                if (totalFilas == negativos)
                {
                    headerCheckBox.CheckState = CheckState.Unchecked;
                }
                else if (totalFilas == positivos)
                {
                    headerCheckBox.CheckState = CheckState.Checked;
                }
                else
                {
                    headerCheckBox.CheckState = CheckState.Indeterminate;
                }
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接