简体   繁体   English

任意列中 DataGridView 的 header 中的复选框

[英]Checkbox in the header of a DataGridView in any column

Actually I have solved the problem of having checkbox in the header of a DGV, here is the code实际上我已经解决了在 DGV 的 header 中有复选框的问题,这里是代码

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);    

Actually First I add a column to my DGV which is a DataGridViewCheckBoxColumn and then in the load of the form adding the code above, my problem is as you can see below for the first column it works great since I can set the rect.X in the code for that column but what about the notifier column how can I know where is the position of the header of this column programmatically since the log column can change through maximizing and this stuffs.实际上,首先我向我的 DGV 添加一个列,它是 DataGridViewCheckBoxColumn,然后在表单的加载中添加上面的代码,我的问题是你可以在下面看到第一列它很好用,因为我可以设置 rect.X该列的代码但是通知列呢?我怎么知道该列的 header 的 position 以编程方式在哪里,因为日志列可以通过最大化和这些东西来改变。

在此处输入图像描述 Finally, How can I know for example what is the position of the header of the column[3] programatically.... Thanks in advance最后,例如,我如何以编程方式知道列 [3] 的 header 的 position 是什么......提前致谢

try this试试这个

#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

This solution works for me, it adds the checkbox to the header cell.这个解决方案对我有用,它将复选框添加到标题单元格中。 You just have to implement the "check all" method and eventually a "on column resize" method (for replace checkbox in the center)您只需要实现“全部检查”方法,并最终实现“列调整大小”方法(用于替换中心的复选框)

// 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
);

The Answer of 56ka is perfekt for me. 56ka 的答案对我来说是完美的。 I just fix the location (2px)我只是固定位置(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;
    }

To me, cleanest solution is from "56ka" and this is my upgrade on it.对我来说,最干净的解决方案来自“56ka”,这是我对它的升级。 With this, you retain an ability to sort and see the sort direction and to have a label next to the checkbox, normal checkbox and all it has to offer.有了这个,您可以保留排序和查看排序方向的能力,并在复选框、普通复选框及其提供的所有内容旁边有一个标签。 Made on .NET Framework 4.0 for DataTable.在 .NET Framework 4.0 上为 DataTable 制作。 Works with DataTable and EF.适用于 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;
}
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);
        }
    }
}

use:采用:

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

You must call the event click on the column By identifying the column you clicked, you can access the desired row and change the value of the corresponding field for example:您必须调用单击该列的事件通过识别您单击的列,您可以访问所需的行并更改相应字段的值,例如:

    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;
        }

    }
    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);
    }

I used the dataGridView_CellPainting event.我使用了 dataGridView_CellPainting 事件。

On that event I put in a conditional statement to set the location of my checkbox within the header cell - eg column 1 row 0.在那个事件中,我放入了一个条件语句来设置我的复选框在标题单元格中的位置 - 例如第 1 列第 0 行。

CellBounds has a number of properties that can be used in setting the location. CellBounds 有许多可用于设置位置的属性。 I took the right of the cell "e.CellBounds.Right" and then subtracted the width of the checkbox to put the checkbox in the right corner of the header cell.我拿了单元格“e.CellBounds.Right”的右边,然后减去复选框的宽度,将复选框放在标题单元格的右上角。

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

Hove missed something when you remove a column and add another at the same index当您删除一列并在同一索引处添加另一列时,Hove 错过了一些东西

add this in the AddHeaderCheckBox function在 AddHeaderCheckBox 函数中添加这个

 Action onColRemoved = () =>
 {
     checkbox.Dispose();
 };
 dgv.ColumnRemoved += (s, e) => onColRemoved();

and modify this :并修改这个:

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;
    }
}

into this进入这个

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;
        }
    }
}

this is another solution for the same problem.这是同一问题的另一种解决方案。 All you have to do is calling the constructor like showed following.您所要做的就是调用构造函数,如下所示。

new ColocarHeaderCheckBox(dataGridView1, colActivo.Index);新的 ColocarHeaderCheckBox(dataGridView1, colActivo.Index);

Saludos.萨卢多斯。

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;
                }
            }
        }
    }
}

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

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