DataGridView CheckBox事件

我正在制作一个DataGridView其中包含一系列Checkbox,水平和垂直方向相同。 任何相同的标签,复选框都将处于非活动状态,我只希望每个组合的两个“检查”之一有效。 以下屏幕截图显示了我的内容: DataGridView http://sofzh.miximages.com/c%23/2e4m3pz.png

在下半部分检查的任何东西,我都需要在鞋帮上进行UN检查。 因此,如果选中[quux,spam](或基于零坐标的[7,8]),我希望[spam,quux]([8,7])未经检查。 到目前为止我所拥有的是以下内容:

  dgvSysGrid.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders; dgvSysGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells; string[] allsysNames = { "heya", "there", "lots", "of", "names", "foo", "bar", "quux", "spam", "eggs", "bacon" }; // Add a column for each entry, and a row for each entry, and mark the "diagonals" as readonly for (int i = 0; i < allsysNames.Length; i++) { dgvSysGrid.Columns.Add(new DataGridViewCheckBoxColumn(false)); dgvSysGrid.Columns[i].HeaderText = allsysNames[i]; dgvSysGrid.Rows.Add(); dgvSysGrid.Rows[i].HeaderCell.Value = allsysNames[i]; // Mark all of the "diagonals" as unable to change DataGridViewCell curDiagonal = dgvSysGrid[i, i]; curDiagonal.ReadOnly = true; curDiagonal.Style.BackColor = Color.Black; curDiagonal.Style.ForeColor = Color.Black; } // Hook up the event handler so that we can change the "corresponding" checkboxes as needed //dgvSysGrid.CurrentCellDirtyStateChanged += new EventHandler(dgvSysGrid_CurrentCellDirtyStateChanged); dgvSysGrid.CellValueChanged += new DataGridViewCellEventHandler(dgvSysGrid_CellValueChanged); } void dgvSysGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e) { Point cur = new Point(e.ColumnIndex, e.RowIndex); // Change the diagonal checkbox to the opposite state DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y]; DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X]; if ((bool)(curCell.Value) == true) { diagCell.Value = false; } else { diagCell.Value = true; } } ///  /// Change the corresponding checkbox to the opposite state of the current one ///  ///  ///  void dgvSysGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { Point cur = dgvSysGrid.CurrentCellAddress; // Change the diagonal checkbox to the opposite state DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y]; DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X]; if ((bool)(curCell.Value) == true) { diagCell.Value = false; } else { diagCell.Value = true; } } 

问题来自于,如果我使用CellValueChanged事件,单元格值的变化似乎总是“落后”,如果我处于“脏”状态,我不知道如何获取当前单元格因为curCell以nullforms出现(暗示当前的单元格地址在某种程度上是错误的,但我没有尝试将该值取出),这意味着该路径根本不起作用。

基本上,如何使用正确的布尔值获取“正确”的地址,以便我的翻转算法可以工作?

最终,它是CurrentCellDirtyStateChanged事件,但你需要以正确的方式做到这一点。 正确的方式是MSDN ,虽然乍一看没有意义。

上面的一个片段,我最终做的是下面的内容:

  // Hook up the event handler so that we can change the "corresponding" checkboxes as needed dgvSysGrid.CurrentCellDirtyStateChanged += new EventHandler(dgvSysGrid_CurrentCellDirtyStateChanged); dgvSysGrid.CellValueChanged += new DataGridViewCellEventHandler(dgvSysGrid_CellValueChanged); } void dgvSysGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e) { Point cur = new Point(e.ColumnIndex, e.RowIndex); // Change the diagonal checkbox to the opposite state DataGridViewCheckBoxCell curCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.X, cur.Y]; DataGridViewCheckBoxCell diagCell = (DataGridViewCheckBoxCell)dgvSysGrid[cur.Y, cur.X]; if ((bool)(curCell.Value) == true) { diagCell.Value = false; } else { diagCell.Value = true; } } void dgvSysGrid_CurrentCellDirtyStateChanged(object sender, EventArgs e) { if (dgvSysGrid.IsCurrentCellDirty) { dgvSysGrid.CommitEdit(DataGridViewDataErrorContexts.Commit); } } 

基本上,所有发生的事情是CurrentCellDirtyStateChanged事件触发CellValueChanged事件,就是这样。 如果您只是附加CellValueChanged事件,那么它只会在您离开单元格后触发。 我不知道原因究竟是什么(考虑到它是一个复选框,是不是立刻“完成”了?),但这就是发生的事情。 并且上面的代码可以正常工作,因为单击它时复选框会更改为RIGHT。 所以它有效。

您可以使用CellValidating事件, e.FormattedValue将具有更改的值。 如果执行某些检查,并且不希望更新该值,请将e.Cancel设置为true。

以下是FormattedValue页面中的示例:

 private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { dataGridView1.Rows[e.RowIndex].ErrorText = ""; int newInteger; // Don't try to validate the 'new row' until finished // editing since there // is not any point in validating its initial value. if (dataGridView1.Rows[e.RowIndex].IsNewRow) { return; } if (!int.TryParse(e.FormattedValue.ToString(), out newInteger) || newInteger < 0) { e.Cancel = true; dataGridView1.Rows[e.RowIndex].ErrorText = "the value must be a non-negative integer"; } } 

我发现最简单的技术是:

  • 注册grid_CellContentClick
  • 使用下面的方法检查单元格的所有行,或者只检查事件处理程序中的行。 我的代码需要从单击的单元格的整个状态重新创建数据模型。

EditedFormattedValue是单元格的“新”值,以及要读取的值。

 var colNumber=0; foreach (var row in grid.Rows) { var dataGridViewCell = (DataGridViewCheckBoxCell)((DataGridViewRow)(row)).Cells[colNumber]; if (dataGridViewCell.EditedFormattedValue) { // This cell is now checked - do whatever you need to with the other cells } }