繁体   English   中英

datagridview中的HeaderCheckbox异常行为

[英]HeaderCheckbox in datagridview strange behaviour

我的datagridview的checkboxColumn中有一个SelectAll的标题复选框

    private void AddSelectAllCheckBox(DataGridView theDataGridView)
    {
        CheckBox cbx = new CheckBox();
        cbx.Name = "SelectAll";
        //The box size
        cbx.Size = new Size(14, 14);

        Rectangle rect = default(Rectangle);
        rect = theDataGridView.GetCellDisplayRectangle(0, -1, true);
        //Put CheckBox in the middle-center of the column header.
        cbx.Location = new System.Drawing.Point(rect.Location.X + ((rect.Width - cbx.Width) / 2), rect.Location.Y + ((rect.Height - cbx.Height) / 2));
        cbx.BackColor = Color.White;
        theDataGridView.Controls.Add(cbx);

        //Handle header CheckBox check/uncheck function
        cbx.Click += HeaderCheckBox_Click;
        //When any CheckBox value in the DataGridViewRows changed,
        //check/uncheck the header CheckBox accordingly.
        //theDataGridView.CellValueChanged += DataGridView_CellChecked;
        //This event handler is necessary to commit new CheckBox cell value right after
        //user clicks the CheckBox.
        //Without it, CellValueChanged event occurs until the CheckBox cell lose focus
        //which means the header CheckBox won't display corresponding checked state instantly when user
        //clicks any one of the CheckBoxes.
        theDataGridView.CurrentCellDirtyStateChanged += DataGridView_CurrentCellDirtyStateChanged;
    }

    private void HeaderCheckBox_Click(object sender, EventArgs e)
    {
        this._IsSelectAllChecked = true;

        CheckBox cbx = default(CheckBox);
        cbx = (CheckBox)sender;

        foreach (DataGridViewRow row in metroGrid1.Rows)
        {

            row.Cells[0].Value = cbx.Checked;

        }

        metroGrid1.EndEdit();

        this._IsSelectAllChecked = false;
    }



    //The CurrentCellDirtyStateChanged event happens after user change the cell value,
    //before the cell lose focus and CellValueChanged event.
    private void DataGridView_CurrentCellDirtyStateChanged(System.Object sender, System.EventArgs e)
    {
        DataGridView dataGridView = (DataGridView)sender;
        if (dataGridView.CurrentCell is DataGridViewCheckBoxCell)
        {
            //When the value changed cell is DataGridViewCheckBoxCell, commit the change
            //to invoke the CellValueChanged event.
            dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
        }
    }

一切正常。

如果我选中或取消选中其行中的复选框,则会触发此事件并起作用:

        private void metroGrid1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
    {
        if (e.ColumnIndex == 0 && e.RowIndex > -1)
        {
            //listBox1.Items.Add(" -> ");
            DataGridView dgv = sender as DataGridView;
            if (dgv == null)
                return;
            //if (dgv.CurrentRow)
            //{
                if (Convert.ToBoolean(dgv.CurrentRow.Cells[Sel.Name].Value) == true)
                {
                    int selCount = Int32.Parse(metroLabel5.Text);
                    int addCount = selCount + Int32.Parse(dgv.CurrentRow.Cells[Jobs.Name].Value.ToString());
                    metroLabel5.Text = addCount.ToString();
                    //listBox1.Items.Add(dgv.CurrentRow.Index.ToString() + " -> " + dgv.CurrentRow.Cells[Jobs.Name].Value.ToString());

                }
                if (Convert.ToBoolean(dgv.CurrentRow.Cells[Sel.Name].Value) == false)
                {
                    int selCount = Int32.Parse(metroLabel5.Text);
                    int minCount = selCount - Int32.Parse(dgv.CurrentRow.Cells[Jobs.Name].Value.ToString());
                    metroLabel5.Text = minCount.ToString();
                   // listBox1.Items.Add(dgv.CurrentRow.Index.ToString() + " -> " + dgv.CurrentRow.Cells[Jobs.Name].Value.ToString());
                }
            //}
        }
    }

    private void metroGrid1_OnCellMouseUp(object sender, DataGridViewCellMouseEventArgs e)
    {
        if (e.ColumnIndex == 0 && e.RowIndex > -1)
        {
            metroGrid1.EndEdit();
        }
    }

我的问题:如果我选中或取消选中headerCheckbox,则为每一行都触发CellValueChanged事件,但是它始终使用事件的第一行。

例如:我有8行,作业分别为1,2,3,4,5,6,7,8,因此,如果全部选中,metrolabel1.text应该为36,但带有selectAll复选框的行将变为8(8个时间行) 0个工作,共1个工作)

您应该使用Convert.ToBoolean(dgv.Rows[e.RowIndex].Cells[Sel.Name].Value)Int32.Parse(dgv.Rows[e.RowIndex].Cells[Jobs.Name].Value.ToString())

该事件针对属于不同行的每个单元格触发,因此,当您要从该行获取值时,应引用针对其触发了该事件的行:

dgv.Rows[e.RowIndex].Cells["Column Name"].Value

现在,在代码中,您将获得dgv.CurrentRow的值。 这不是您所需要的。

暂无
暂无

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

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