[英]C# datagridview row toggle
我正在寻找有关datagridview的帮助。
我想做的是,当我单击receiveview(datagridview)列表中的一个项目(一行)时,它应该切换该行的选择(即,如果它已被选择,它将取消选择,反之亦然)。
到目前为止,我已经找到了以下代码,但是,这并非一直有效:
private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (!_selectionChanged)
{
//do other stuff here
receiptView.ClearSelection();
_selectionChanged = true;
}
else
{
//do other stuff here
_selectionChanged = false;
}
}
private void receiptView_SelectionChanged(object sender, EventArgs e)
{
_selectionChanged = true;
}
当单击某行并且没有选择任何行或者已经选择了某行并且现在选择了新行时,它将按以下顺序触发事件:
发生的事情是,当我非常快地选择/取消选择一行时(类似于双击),最终将“取消同步”实际的选择状态和_selectionChanged 。 我的意思是:
并非每次我快速点击都会发生这种情况,但它会定期发生(大约每第二/第三次点击对)。 如果我缓慢而故意地单击,就永远不会发生。
我真的不知道为什么会这样,但是我怀疑由于点击1和点击2发生得非常接近,当第二个点击事件仍在运行时会触发第二个点击事件,导致第一次点击将_selectionChanged更改为false,并且第二个将其更改回true,同时保持选定的行。 但是,由于我没有创建任何新线程,并且所有线程都在主UI线程上运行,因此它不应该是序列化的执行吗? 即单击1的事件触发器,一旦完成,单击2的事件触发器?
如果你们中的任何一个知道一种更简单的方法(在datagridview中切换),或者可以看到错误和/或找到解决方案,将不胜感激。
谢谢。
TL; DR
您的第二次点击被CellDoubleClick
事件劫持。 使用您的CellClick
事件处理程序中的相同代码来订阅它。
-请参阅答案末尾的解决方案 。
调试说明
为了演示正在发生的事情,我们将以下输出添加到您的方法中,然后运行您在OP中描述的场景。
private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
{
if (!_selectionChanged)
{
Console.WriteLine("Cleared.......");
receiptView.ClearSelection(); // NOTE: Triggers SelectionChanged event.
_selectionChanged = true;
}
else
{
Console.WriteLine("Highlighted...");
_selectionChanged = false;
}
}
private void receiptView_SelectionChanged(object sender, EventArgs e)
{
Console.WriteLine("Changed!");
_selectionChanged = true;
}
当前未选择任何行,以下测试,预期结果和实际结果:
+======================+=================+================+=================+
| ACTION | EXPECTED OUTPUT | ACTUAL OUTPUT | GUI RESULTS |
+======================+=================+================+=================+
| Single-click 1st row | Changed!* | Changed!* | Row Highlighted |
| | Highlighted... | Highlighted... | |
+----------------------+-----------------+----------------+-----------------+
| Double-click 1st row | Cleared....... | Cleared....... | Row Highlighted |
| | Changed!^ | Changed!^ | |
| | Changed!* | Changed!* | |
| | Highlighted... | | |
+----------------------+-----------------+----------------+-----------------+
| Single-click 1st row | Cleared....... | Highlighted... | Row Highlighted |
| | Changed!^ | | (Still...?) |
+----------------------+-----------------+----------------+-----------------+
* SelectionChanged在后面的代码中触发; 现在选择了未选中的行。
^通过调用ClearSelection()触发SelectionChanged。
分析 :第一次单击将触发SelectionChanged
并按预期突出显示该行。 接下来, 双击该行,认为第一次单击将清除该行(您将手动导致该行触发SelectionChanged
),第二次单击(再次在背景中触发SelectionChanged
)再次突出显示该行。 这是我们出问题的地方。
通过双击 ,第一次单击将按预期触发clear和SelectionChanged
事件。 我们甚至从SelectionChanged
看到了第二个预期的打印输出,但是没有从CellClick
事件中看到突出显示的打印输出。 为什么?
单击一次行/单元格时,将触发CellClick
。 当您快速连续单击两次时, CellClick
触发第一次单击,而CellDoubleClick
触发第二次单击。 因此,您的第一次点击将按预期方式命中您的代码。 第二次单击永远不会命中您的代码,除了在后台仍然选择了未选择的行,因此SelectionChanged
仍会再次触发。 从这一点开始,您的_selectionChanged
标志已关闭-导致更多不准确的结果。
解决方案 :订阅CellDoubleClick
事件并执行它相同的代码在CellClick
,你会没事的。
private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
{
this.DoStuff();
}
private void receiptView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
this.DoStuff();
}
private void DoStuff()
{
if (!_selectionChanged)
{
//do other stuff here
receiptView.ClearSelection();
_selectionChanged = true;
}
else
{
//do other stuff here
_selectionChanged = false;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.