ListView選取多項目後,選取單一項目的重複執行事件問題

  • 2920
  • 0
  • 2011-10-05

簡介: ListView控制項常常會用到SelectedIndexChanged事件處理已選取的項目。

現在假設Items中有4個項目,並針對以下情況做說明。

簡介: ListView控制項常常會用到SelectedIndexChanged事件處理已選取的項目。

 

 

現在假設Items中有4個項目,並針對以下情況做說明。

 

情況1:

在毫無選取的狀況下點擊索引2項目,將會觸發一次SelectedIndexChanged事件,接著在點擊索引3的項目,則會觸發兩次SelectedIndexChanged事件。

 

這是第二次點擊後,因為第一次已經選取索引2項目了,所以內部會先從索引0到索引3一個一個項目都做檢查是否已選取,若已選取的話,則會取消已選取的項目,這時候就會觸發SelectedIndexChanged事件,則這時SelectedIndices.Count的數量會等於0,最後內部在將第二次點擊的索引3做為已選取狀態,此時又會觸發SelectedIndexChanged事件,所以總共是兩次。

 

情況2:

先將所有項目都選取,之後點擊索引1,這樣則會觸發3次SelectedIndexChanged事件。

 

與情況1個解相同原理,內部會先取消索引0選取,此時觸發SelectedIndexChanged事件,在取消索引2的選取,此時再次觸發SelectedIndexChanged事件,最後取消索引3的選取,觸發SelectedIndexChanged事件,所以總共會觸發三次。

 

 

 

實際應用的問題點: 假設使用者大量選取項目時,之後又只選取一項,可想而知會造成多次觸發事件,若事件中寫著大量更新的代碼,則會造成效率上面的影響,應該避免這種情況。

 

 

簡易的避免實作方式:

   1:      public partial class ListViewEx : ListView
   2:      {
   3:   
   4:          private bool isSelectedIndexChanged = false;                // 記錄當選取的索引改變時狀態。
   5:          private bool canRaisingAnSelectedIndexChanged = false;      // 記錄是否可以呼叫SelectedIndexChanged事件。
   6:   
   7:   
   8:          protected override void OnClick(EventArgs e)
   9:          {
  10:              //
  11:              // 當選取索引有改變且目前有選取項目時,則觸發OnSelectedIndexChanged方法。
  12:              //
  13:              if (isSelectedIndexChanged && this.SelectedIndices.Count != 0)
  14:              {
  15:                  canRaisingAnSelectedIndexChanged = true;
  16:                  OnSelectedIndexChanged(new EventArgs());
  17:              }
  18:              
  19:              base.OnClick(e);
  20:          }
  21:   
  22:          protected override void OnSelectedIndexChanged(EventArgs e)
  23:          {
  24:              //
  25:              // 當內部在取消選取索引時,可能會經過SelectedIndices.Count數量為0的時候,這時候應避免執行。
  26:              //
  27:              if (this.SelectedIndices.Count == 0) return;
  28:              //
  29:              // 最先被使用者點擊則記錄確認已選擇索引已更變。
  30:              //
  31:              isSelectedIndexChanged = true;
  32:              //
  33:              // 等待內部取消索引完成後,透過比較後面觸發的OnClick方法來執行OnSelectedIndexChanged方法。
  34:              //
  35:              if (!canRaisingAnSelectedIndexChanged) return;
  36:              //
  37:              // 避免使用者重新點擊已選取項目,而執行OnClick方法讓OnSelectedIndexChanged方法又執行一次。
  38:              //
  39:              isSelectedIndexChanged = false;
  40:              //
  41:              // 避免下次觸發OnSelectedIndexChanged方法的初始設定。
  42:              //
  43:              canRaisingAnSelectedIndexChanged = false;
  44:              //
  45:              // 觸發 SelectedIndexChanged 事件。
  46:              //
  47:              base.OnSelectedIndexChanged(e);
  48:          }
  49:      }

 

 

 

 

 

 

 

 

如此一來,每次選取項目時,SelectedIndexChanged事件只會被觸發一次,這樣可以避免SelectedIndexChanged事件裡面的代碼重複執行。

 

引用文章請註明出處與作者,謝謝。

作者: jGame

日期: 2011/09/11