[英]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.