• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
求真 务实
代码简单,高效,易懂才是好代码.
博客园    首页    新随笔    联系   管理    订阅  订阅

DataGridView中实现checkbox全选的自定义控件

在DataGridView中实现Checkbox的全选的方法就是在列头画一个checkbox, 并给其一个事件.

这个之前很多blog都有写, 这里就不多废话了,  codeproject上面有示例代码.

这里我们再多做一层的封装,将其封装成一个控件,这样的话, 我们就可以最大程度上的复用, 而不需要老是重复写同样的, 无聊的代码了!

思路如下:

继承DataGridViewCheckBoxColumn类, 更改它的headerCell的样式. 添加cellValueChanged时间,使在进行复选框选择的时候可以触发事件,从而进行处理.

继承DataGridViewColumnHeaderCell类, 重新绘制一个带CheckBox的HeaderCell

 

话不多说直接上代码了, 如果有不懂的欢迎留言:

public class DataGridViewCheckBoxColumnSelectAll : DataGridViewCheckBoxColumn
    {
        private DatagridViewCheckBoxHeaderCell headerCell;
        private bool loaded;

        public event CheckBoxClickedHandler OnCheckBoxClicked;
        int TotalCheckedCheckBoxes = 0;
        bool IsHeaderCheckBoxClicked = false;

        public DataGridViewCheckBoxColumnSelectAll()
        {
            this.headerCell = new DatagridViewCheckBoxHeaderCell();
            base.HeaderCell = this.headerCell;

            this.headerCell.OnCheckBoxClicked += new CheckBoxClickedHandler(this.headerCell_OnCheckBoxClicked);
            this.loaded = false;
           
        }

        public DataGridViewCheckBoxColumnSelectAll(bool threeState)
            : base(threeState)
        {
            this.headerCell = new DatagridViewCheckBoxHeaderCell();
            base.HeaderCell = this.headerCell;
        }

        /// <summary>
        /// 在DataGridView改变时进行事件的绑定
        /// </summary>
        protected override void OnDataGridViewChanged()
        {
            if (this.DataGridView!=null)
            {
                this.DataGridView.CellValueChanged -= DataGridView_CellValueChanged;
                this.DataGridView.CellValueChanged += DataGridView_CellValueChanged;
                this.DataGridView.CurrentCellDirtyStateChanged -= DataGridView_CurrentCellDirtyStateChanged;
                this.DataGridView.CurrentCellDirtyStateChanged += DataGridView_CurrentCellDirtyStateChanged;
            }
        }

        /// <summary>
        /// 在复选的时候进行判断.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex>=0&&e.ColumnIndex>=0)
            {
                if (!IsHeaderCheckBoxClicked)
                    RowCheckBoxClick((DataGridViewCheckBoxCell)this.DataGridView[e.ColumnIndex, e.RowIndex]);
            }
           
        }

        /// <summary>
        /// 在复选框被选中的时候触发该事件, 该事件用于触发ValueChanged事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e)
        {
            if (this.DataGridView.CurrentCell is DataGridViewCheckBoxCell)
                this.DataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }

        /// <summary>
        /// 复选框被点击时所需要做的操作
        /// </summary>
        /// <param name="checkBox"></param>
        private void RowCheckBoxClick(DataGridViewCheckBoxCell checkBox)
        {
            var head = this.headerCell as DatagridViewCheckBoxHeaderCell;
            if (checkBox != null)
            {
                //计算所有被选中的行的数量 
                if ((bool)checkBox.Value && TotalCheckedCheckBoxes < this.DataGridView.RowCount)
                    TotalCheckedCheckBoxes++;
                else if (TotalCheckedCheckBoxes > 0)
                    TotalCheckedCheckBoxes--;

                //当所有复选框都被选中的时候,列的头上的复选框被选中, 反之则不被选中.
                if (TotalCheckedCheckBoxes < this.DataGridView.RowCount)
                    head.IsChecked = false;
                else if (TotalCheckedCheckBoxes == this.DataGridView.RowCount)
                    head.IsChecked = true;
                //强制repained
                head.DataGridView.InvalidateCell(head);
            }
        }


        /// <summary>
        /// 头被选中时触发OnCheckBoxClicked事件.
        /// </summary>
        /// <param name="state"></param>
        private void headerCell_OnCheckBoxClicked(bool state)
        {
            if (this.OnCheckBoxClicked != null)
            {
                this.OnCheckBoxClicked(state);
            }
        }

    }
 public delegate void CheckBoxClickedHandler(bool state);

    internal class DatagridViewCheckBoxHeaderCell : DataGridViewColumnHeaderCell
    {
        private CheckBoxState _cbState = CheckBoxState.UncheckedNormal;
        private Point _cellLocation = new Point();
        private bool _checked;
        private Point checkBoxLocation;
        private Size checkBoxSize;

        public bool IsChecked
        {
            get
            {
                return _checked;
            }

            set
            {
                _checked = value;
                if (this._checked)
                {
                    this._cbState = CheckBoxState.CheckedNormal;
                }
                else
                {
                    this._cbState = CheckBoxState.UncheckedNormal;
                }
            }
        }

        public event CheckBoxClickedHandler OnCheckBoxClicked;

        /// <summary>
        /// 点击列头的时候触发的事件,这里有个判断, 如果点击的位置是复选框则触发OnCheckBoxClicked事件.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
        {
            Point point = new Point(e.X + this._cellLocation.X, e.Y + this._cellLocation.Y);
            if (((point.X >= this.checkBoxLocation.X) && (point.X <= (this.checkBoxLocation.X + this.checkBoxSize.Width))) && ((point.Y >= this.checkBoxLocation.Y) && (point.Y <= (this.checkBoxLocation.Y + this.checkBoxSize.Height))))
            {
                this._checked = !this._checked;
                bool temp = this._checked;
                if (this.OnCheckBoxClicked != null)
                {
                    this.OnCheckBoxClicked(this._checked);
                    base.DataGridView.InvalidateCell(this);
                }
                foreach (DataGridViewRow row in base.DataGridView.Rows)
                {
                    ((DataGridViewCheckBoxCell)row.Cells[e.ColumnIndex]).Value = temp;
                }
                base.DataGridView.RefreshEdit();

            }
            base.OnMouseClick(e);
        }

        /// <summary>
        /// 绘制一个CheckBox
        /// </summary>
        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)
        {
            base.Paint(graphics, clipBounds, cellBounds, rowIndex, dataGridViewElementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
            Point point = new Point();
            Size glyphSize = CheckBoxRenderer.GetGlyphSize(graphics, CheckBoxState.UncheckedNormal);
            point.X = (cellBounds.Location.X + (cellBounds.Width / 2)) - (glyphSize.Width / 2);
            point.Y = (cellBounds.Location.Y + (cellBounds.Height / 2)) - (glyphSize.Height / 2);
            this._cellLocation = cellBounds.Location;
            this.checkBoxLocation = point;
            this.checkBoxSize = glyphSize;
            if (this._checked)
            {
                this._cbState = CheckBoxState.CheckedNormal;
            }
            else
            {
                this._cbState = CheckBoxState.UncheckedNormal;
            }
            CheckBoxRenderer.DrawCheckBox(graphics, this.checkBoxLocation, this._cbState);
        }

       

       
       
    }

  源码位置:

http://pan.baidu.com/s/1jGJzErs

posted @ 2015-02-26 10:09  Dino H.Y  阅读(2053)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3