天天看點

Winform傳統DataGridView和DevExpress控件的GridControl兩者表頭全選功能的實作

在開發一個個人項目的時候,有客戶反映預設GridView多選操作不是很友善和理想,想在清單的左邊增加一列可以勾選,并且最好支援清單頭部全選的操作,否則資料多的時候一個個勾選要到天荒地老。

基于以上需求,找了不少例子進行比較,并對代碼進行測試改進,終于完成了以上的功能了, 并且由于我本身做了多套界面的處理,是以,基于傳統的DataGridView全選操作不能少,而且基于DevExpress控件的GridView全選操作也應該支援,呵呵。

無圖無真相,下面先上圖介紹兩種不同的效果,然後在詳細介紹代碼的實作。

1)DevExpress控件的GridView的實作多選操作

先講DevExpress控件的GridView的實作,要實作的功能基本上是處理單擊全選操作、重新繪制表頭等操作,首先在加載第一步實作相關的事件和操作,如下所示。

 this.gridView1.Click += new System.EventHandler(this.gridView1_Click);

 this.gridView1.CustomDrawColumnHeader += new DevExpress.XtraGrid.Views.Grid.ColumnHeaderCustomDrawEventHandler(this.gridView1_CustomDrawColumnHeader);

 this.gridView1.DataSourceChanged += new EventHandler(gridView1_DataSourceChanged);

然後就是實作裡面的事件操作了,對應的代碼如下所示。

        private void gridView1_Click(object sender, EventArgs e)

        {

            if (DevControlHelper.ClickGridCheckBox(this.gridView1, "Check", m_checkStatus))

            {

                m_checkStatus = !m_checkStatus;

            }

        }

        private void gridView1_CustomDrawColumnHeader(object sender, DevExpress.XtraGrid.Views.Grid.ColumnHeaderCustomDrawEventArgs e)

            if (e.Column != null && e.Column.FieldName == "Check")

                e.Info.InnerElements.Clear();

                e.Painter.DrawObject(e.Info);

                DevControlHelper.DrawCheckBox(e, m_checkStatus);

                e.Handled = true;

        void gridView1_DataSourceChanged(object sender, EventArgs e)

            GridColumn column = this.gridView1.Columns.ColumnByFieldName("Check");

            if (column != null)

                column.Width = 80;

                column.OptionsColumn.ShowCaption = false;

                column.ColumnEdit = new RepositoryItemCheckEdit();

       }

其中單擊和繪制表頭的操作,交給另外一個類DevControlHelper來獨立進行處理,資料源變化gridView1_DataSourceChanged實作的操作是尋找對應的全選列,并設定列寬、隐藏表頭标題,并設定為複選框樣式。

DevControlHelper 類的實作代碼如下所示:

        public static void DrawCheckBox(DevExpress.XtraGrid.Views.Grid.ColumnHeaderCustomDrawEventArgs e, bool chk)

            RepositoryItemCheckEdit repositoryCheck = e.Column.ColumnEdit as RepositoryItemCheckEdit;

            if (repositoryCheck != null)

                Graphics g = e.Graphics;

                Rectangle r = e.Bounds;

                DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo info;

                DevExpress.XtraEditors.Drawing.CheckEditPainter painter;

                DevExpress.XtraEditors.Drawing.ControlGraphicsInfoArgs args;

                info = repositoryCheck.CreateViewInfo() as DevExpress.XtraEditors.ViewInfo.CheckEditViewInfo;

                painter = repositoryCheck.CreatePainter() as DevExpress.XtraEditors.Drawing.CheckEditPainter;

                info.EditValue = chk;

                info.Bounds = r;

                info.CalcViewInfo(g);

                args = new DevExpress.XtraEditors.Drawing.ControlGraphicsInfoArgs(info, new DevExpress.Utils.Drawing.GraphicsCache(g), r);

                painter.Draw(args);

                args.Cache.Dispose();

        public static bool ClickGridCheckBox(DevExpress.XtraGrid.Views.Grid.GridView gridView, string fieldName, bool currentStatus)

            bool result = false;

            if (gridView != null)

                gridView.ClearSorting();//禁止排序

                gridView.PostEditor();

                DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitInfo info;

                Point pt = gridView.GridControl.PointToClient(Control.MousePosition);

                info = gridView.CalcHitInfo(pt);

                if (info.InColumn && info.Column != null && info.Column.FieldName == fieldName)

                {

                    for (int i = 0; i < gridView.RowCount; i++)

                    {

                        gridView.SetRowCellValue(i, fieldName, !currentStatus);

                    }

                    return true;

                }

            return result;

        } 

2)傳統DataGridView實作全選操作

首先在第一列增加一個CheckBox控件,然後通過相關的事件,調整其位置,并相應對應的單擊全選操作,初始化代碼如下所示。

        CheckBox HeaderCheckBox = null;

        public FrmNormalGridViewSelect()

            InitializeComponent();

            if (!this.DesignMode)

                HeaderCheckBox = new CheckBox();

                HeaderCheckBox.Size = new Size(15, 15);

                this.dgvSelectAll.Controls.Add(HeaderCheckBox);

                HeaderCheckBox.KeyUp += new KeyEventHandler(HeaderCheckBox_KeyUp);

                HeaderCheckBox.MouseClick += new MouseEventHandler(HeaderCheckBox_MouseClick);

                dgvSelectAll.CurrentCellDirtyStateChanged += new EventHandler(dgvSelectAll_CurrentCellDirtyStateChanged);

                dgvSelectAll.CellPainting += new DataGridViewCellPaintingEventHandler(dgvSelectAll_CellPainting);

    }

事件實作了CheckBox重繪調整,并處理單擊事件,如下所示。

        private void HeaderCheckBox_MouseClick(object sender, MouseEventArgs e)

            HeaderCheckBoxClick((CheckBox)sender);

        private void dgvSelectAll_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)

            if (e.RowIndex == -1 && e.ColumnIndex == 0)

                    ResetHeaderCheckBoxLocation(e.ColumnIndex, e.RowIndex);

        private void ResetHeaderCheckBoxLocation(int ColumnIndex, int RowIndex)

            Rectangle oRectangle = this.dgvSelectAll.GetCellDisplayRectangle(ColumnIndex, RowIndex, true);

            Point oPoint = new Point();

            oPoint.X = oRectangle.Location.X + (oRectangle.Width - HeaderCheckBox.Width) / 2 + 1;

            oPoint.Y = oRectangle.Location.Y + (oRectangle.Height - HeaderCheckBox.Height) / 2 + 1;

            HeaderCheckBox.Location = oPoint;

        private void HeaderCheckBoxClick(CheckBox HCheckBox)

            foreach (DataGridViewRow Row in dgvSelectAll.Rows)

                ((DataGridViewCheckBoxCell)Row.Cells["chkBxSelect"]).Value = HCheckBox.Checked;

            dgvSelectAll.RefreshEdit();