I'm looking to get some help with the datagridview.
What I want to do is when I click an item (a row) in the receiptView (datagridview) list, it should toggle that row's selection (ie If it was already selected, it would deselect and vice-versa).
So far I've found this code, however, this doesn't work all the time:
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;
}
When a row is clicked and no row is already selected OR a row is already selected and a new row is now selected it triggers the events in this following order:
What's happening is that when I select/deselect a row really quickly (akin to like a double click) it would end up "de-syncing" the actual selection state and _selectionChanged . What I mean by this is that:
This doesn't happen every time I click quickly but it does happens regularly (about every second/third click-pair). It NEVER happens if I click slowly and deliberately.
I don't really know why this is happening but I suspect that as Clicks 1 and 2 happen very close to one another, the second click's event triggers while the first's is still running, causing the first click to change the _selectionChanged to false, and the second to change it back to true, while keeping the row selected. However, since I'm not creating any new threads and this is all running on the main UI thread, should it not be a serialized execution? ie Click 1's events trigger, and once it has completed, click 2's events trigger?
If any of you know an easier way to do this (toggling in a datagridview), or can see the bug and/or have a solution it would be greatly appreciated.
Thanks.
TL;DR
Your second click is being hijacked by the CellDoubleClick
event. Subscribe to it using the same code from your CellClick
event handler.
- See the Solution at the end of the answer.
DEBUGGING EXPLANATION
To demonstrate what's happening, we add the following outputs to your methods, then run through the scenario you described in the 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;
}
With no rows currently selected, the following test, expected results, and actual results:
+======================+=================+================+=================+
| 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 triggered in behind code; non-selected row is now selected.
^ SelectionChanged triggered by call to ClearSelection().
Analysis : Your first click triggers SelectionChanged
and highlights the row as expected. Next, you double-click the row, thinking the first click will clear the row (which you will manually cause to trigger SelectionChanged
), and the second click (again, triggering SelectionChanged
in the background) re-highlights it. This is where we go wrong.
From the double-click , the first click triggers the clear and SelectionChanged
event as expected. We even see the second expected printout from SelectionChanged
, but not the highlight printout from the CellClick
event. Why?
When you click on a row/cell once, CellClick
is triggered. When you click twice in quick succession, CellClick
triggers for the first click and CellDoubleClick
triggers for the second click. Thus, your first click hits your code as expected. The second click never hits your code, except that in the background the non-selected row was still selected and thus SelectionChanged
is still triggered a second time. From this point on, your _selectionChanged
flag is off - causing more inaccurate results.
Solution : Subscribe to the CellDoubleClick
event and perform the same code in it as in CellClick
and you'll be fine.
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;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.