C# 如何强制a";刷新“;在DataGridView中
我是一个新手,正在做我的第一个C#项目(在Haskell和C方面也只有很少的经验),寻找如何在我的程序中实现一个小功能的指导 我有一个DataGridView表(其中有3列复选框)供用户填写。当在一行中选中第二个复选框时,必须取消选中第一个复选框。我已经可以这样做了,但问题是,第一个选中的只有在我在表中选择其他内容后才会被取消选中 以下是有关CellValueChanged事件的代码(注释中的内容是我试图帮助我的内容)C# 如何强制a";刷新“;在DataGridView中,c#,winforms,datagridview,C#,Winforms,Datagridview,我是一个新手,正在做我的第一个C#项目(在Haskell和C方面也只有很少的经验),寻找如何在我的程序中实现一个小功能的指导 我有一个DataGridView表(其中有3列复选框)供用户填写。当在一行中选中第二个复选框时,必须取消选中第一个复选框。我已经可以这样做了,但问题是,第一个选中的只有在我在表中选择其他内容后才会被取消选中 以下是有关CellValueChanged事件的代码(注释中的内容是我试图帮助我的内容) if(e.ColumnIndex==0 | | e.ColumnIndex=
if(e.ColumnIndex==0 | | e.ColumnIndex==1 | | tabela_NormasDataGridView.Rows.Count==0)
{
返回;
}
var isChecked=(bool)tabela_NormasDataGridView.Rows[e.RowIndex]。Cells[e.ColumnIndex]。Value;
如果(已检查)
{
对于(int i=2;i<5;i++)
{
//Console.WriteLine(“og”+e.ColumnIndex);
DataGridViewCell cell=tabela_NormasDataGridView.Rows[e.RowIndex].Cells[i];
//Console.WriteLine(“segunda”+cell.ColumnIndex);
if(cell.ColumnIndex!=e.ColumnIndex)
{
cell.Value=false;
//这个。刷新();
}
}
}
在连接某些事件以执行某些操作时,明智的做法是小心谨慎。为什么某个特定事件不一定适合您希望代码在该事件中执行的操作,这一点可能不太明显
换句话说,代码可以工作,并且不会崩溃,但是查看引擎盖下可能会发现代码正在执行您可能不希望执行的步骤。这通常是无害的,只会浪费CPU周期。它还可能导致代码崩溃
一个更微妙的问题可能会出现,其中一个网格事件会浪费大量CPU周期,从而导致使用网格的应用程序变得迟钝。例子;如果网格定位到可调整大小的控件中,并且用户调整控件的大小。调整网格大小时,用户可能会在重新绘制网格时看到结巴
在当前代码中,当执行以下行时
cell.Value = false;
单元格的值将被更改。这看起来无害,但是该代码在网格的CellValueChanged
事件中。。。代码是“更改单元格值”。这将导致事件再次触发。在这种情况下,我们真的不希望这样
LarsTech的解决方案将起作用,我们将在下面的示例中使用它,但是,应该注意的是,该解决方案在执行过程中会产生额外的不必要步骤
关于可能的简单解决方案…
避免这种重新触发的一种可能的解决方案是在代码将单元格值设置为false之前“关闭”网格的CellValueChanged
事件。
然后在代码更改值后将其重新“打开”
另一个使用不同网格事件的选项…
另一个可能(更好)的解决方案是更改代码所在的事件。如果您连接网格的CellContentClick
事件,就可以完成此操作
使用CellContnetClick
事件的关键优势在于它将在网格的CellValueChanged
事件触发之前触发。这将允许代码“更改”单元格值,它们将立即更新,因为当代码更改值时,网格的CellValueChanged
事件将“自动”触发
一个完整的示例…
为了帮助将其可视化,下面是一个示例。将两个DataGridView
放到表单上。
需要做的唯一更改是将顶部网格名称更改为tabela\u NormasDataGridView
。这些列将添加到代码中
在下图的左侧可以看到两个网格。在本例中,两个网格连接相同的事件。连线事件是
CellValueChanged
,CurrentCellDirtyStateChanged
和CellContentClick
事件
在每个事件中,Debug
语句被添加到“当”事件“进入”和“当”事件“退出”(离开)时的输出中
顶部网格事件中有哪些代码
-此事件包含我们的代码CellValueChanged
-此事件包含要“提交”的代码 编辑CurrentCellDirtyStateChanged
-此事件不包含任何代码CellContentClick
-此事件不包含任何代码CellValueChanged
-此事件不包含任何代码CurrentCellDirtyStateChanged
-此事件包含我们的代码CellContentClick
- 我们可以看到网格
事件 首先触发,该事件中的代码将编辑提交到 网格。它被输入…但是 。。。我们可以看到,它并没有立即“离开”事件。至少 还没有。事实上,该事件在事件列表中被重新输入 调试语句。我们还可以看到此事件被触发了两次CurrentCellDirtyStateChanged
- 接下来,我们有六(6)个对grids
事件的调用。 初始情况下,事件在完成之前重新输入(输入) 调用网格CellValueChanged
事件六(6)次 想要更改两个单元格,是“创建”不必要的工作。在里面 此外,这将为代码打开无限循环的可能性CellValueChanged
- 在对事件的六次调用(代码所在的位置)之后,我们可以看到
CurrentCellDirtyStateChanged
cell.Value = false;
private void Form1_Load(object sender, EventArgs e) { AddCheckBoxColumnsToGrid(tabela_NormasDataGridView); tabela_NormasDataGridView.CellValueChanged += new DataGridViewCellEventHandler(tabela_NormasDataGridView_CellValueChanged); tabela_NormasDataGridView.CurrentCellDirtyStateChanged += new EventHandler(tabela_NormasDataGridView_CurrentCellDirtyStateChanged); tabela_NormasDataGridView.CellContentClick += new DataGridViewCellEventHandler(tabela_NormasDataGridView_CellContentClick); AddCheckBoxColumnsToGrid(dataGridView2); dataGridView2.CellValueChanged += new DataGridViewCellEventHandler(dataGridView2_CellValueChanged); dataGridView2.CurrentCellDirtyStateChanged += new EventHandler(dataGridView2_CurrentCellDirtyStateChanged); dataGridView2.CellContentClick += new DataGridViewCellEventHandler(dataGridView2_CellContentClick); } private void AddCheckBoxColumnsToGrid(DataGridView dgv) { DataGridViewTextBoxColumn txtCol = new DataGridViewTextBoxColumn(); txtCol.Name = "col0"; dgv.Columns.Add(txtCol); txtCol = new DataGridViewTextBoxColumn(); txtCol.Name = "col0"; dgv.Columns.Add(txtCol); DataGridViewCheckBoxColumn col = new DataGridViewCheckBoxColumn(); col.Name = "Check1"; dgv.Columns.Add(col); col = new DataGridViewCheckBoxColumn(); col.Name = "Check2"; dgv.Columns.Add(col); col = new DataGridViewCheckBoxColumn(); col.Name = "Check3"; dgv.Columns.Add(col); dgv.Rows.Add(4); }
private void tabela_NormasDataGridView_CellValueChanged(object sender, DataGridViewCellEventArgs e) { Debug.WriteLine("DGV1 - Cell Value Changed -> enter"); if (e.ColumnIndex == 0 || e.ColumnIndex == 1 || tabela_NormasDataGridView.Rows.Count == 0) { return; } var isChecked = (bool)tabela_NormasDataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; if (isChecked) { for (int i = 2; i < 5; i++) { DataGridViewCell cell = tabela_NormasDataGridView.Rows[e.RowIndex].Cells[i]; if (cell.ColumnIndex != e.ColumnIndex) { cell.Value = false; } } } Debug.WriteLine("DGV1 - Cell Value Changed -> leave"); } private void tabela_NormasDataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e) { Debug.WriteLine("DGV1 - Current Cell Dirty Cell State Changed -> enter"); tabela_NormasDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); Debug.WriteLine("DGV1 - Current Cell Dirty Cell State Changed -> leave"); } private void tabela_NormasDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e) { Debug.WriteLine("DGV1 - CellContentClick -> enter"); // Do nothing Debug.WriteLine("DGV1 - CellContentClick -> leave"); }
private void dataGridView2_CellValueChanged(object sender, DataGridViewCellEventArgs e) { Debug.WriteLine("DGV2 - Cell Value Changed -> enter"); // do nothing Debug.WriteLine("DGV2 - Cell Value Changed -> leave"); } private void dataGridView2_CurrentCellDirtyStateChanged(object sender, EventArgs e) { Debug.WriteLine("DGV2 - Current Cell Dirty Cell State Changed -> enter"); // do nothing //dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit); Debug.WriteLine("DGV2 - Current Cell Dirty Cell State Changed -> leave"); } private void dataGridView2_CellContentClick(object sender, DataGridViewCellEventArgs e) { Debug.WriteLine("DGV2 - Cell Content Click -> enter"); string colName = dataGridView2.Columns[e.ColumnIndex].Name; if (colName == "Check1" || colName == "Check2" || colName == "Check3") { int rowIndex = e.RowIndex; switch (colName) { case "Check1": dataGridView2.Rows[rowIndex].Cells["Check2"].Value = false; dataGridView2.Rows[rowIndex].Cells["Check3"].Value = false; break; case "Check2": dataGridView2.Rows[rowIndex].Cells["Check1"].Value = false; dataGridView2.Rows[rowIndex].Cells["Check3"].Value = false; break; case "Check3": dataGridView2.Rows[rowIndex].Cells["Check1"].Value = false; dataGridView2.Rows[rowIndex].Cells["Check2"].Value = false; break; } } Debug.WriteLine("DGV2 - Cell Content Click -> leave"); }
void tabela_NormasDataGridView_CurrentCellDirtyStateChanged(object sender, EventArgs e) { tabela_NormasDataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit); }