Dot-Net

如何避免數千個不必要的 ListView.SelectedIndexChanged 事件?

  • February 21, 2017

如果使用者選擇 .NET 2.0 ListView 中的所有項目,ListView 將為每個項目觸發SelectedIndexChanged事件,而不是觸發事件以指示選擇已更改。

如果使用者隨後點擊以選擇列表中的一個項目,則 ListView 將為每個未選擇的項目觸發SelectedIndexChanged事件,然後為單個新選擇的項目觸發SelectedIndexChanged事件,而不是觸發一個事件來指示選擇已經改變。

如果您在SelectedIndexChanged事件處理程序中有程式碼,則當您開始在列表中有數百/數千個項目時,程序將變得非常無響應。

我考慮過駐留計時器等。

但是有沒有人有一個很好的解決方案來避免數千個不必要的 ListView。SelectedIndexChange事件,什麼時候真的會發生一個事件

伊恩的好解決方案。我把它做成了一個可重用的類,確保正確處理計時器。我還縮短了獲取響應速度更快的應用程序的時間間隔。該控制項還具有雙緩衝以減少閃爍。

 public class DoublebufferedListView : System.Windows.Forms.ListView
 {
    private Timer m_changeDelayTimer = null;
    public DoublebufferedListView()
       : base()
    {
       // Set common properties for our listviews
       if (!SystemInformation.TerminalServerSession)
       {
          DoubleBuffered = true;
          SetStyle(ControlStyles.ResizeRedraw, true);
       }
    }

    /// <summary>
    /// Make sure to properly dispose of the timer
    /// </summary>
    /// <param name="disposing"></param>
    protected override void Dispose(bool disposing)
    {
       if (disposing && m_changeDelayTimer != null)
       {
          m_changeDelayTimer.Tick -= ChangeDelayTimerTick;
          m_changeDelayTimer.Dispose();
       }
       base.Dispose(disposing);
    }

    /// <summary>
    /// Hack to avoid lots of unnecessary change events by marshaling with a timer:
    /// http://stackoverflow.com/questions/86793/how-to-avoid-thousands-of-needless-listview-selectedindexchanged-events
    /// </summary>
    /// <param name="e"></param>
    protected override void OnSelectedIndexChanged(EventArgs e)
    {
       if (m_changeDelayTimer == null)
       {
          m_changeDelayTimer = new Timer();
          m_changeDelayTimer.Tick += ChangeDelayTimerTick;
          m_changeDelayTimer.Interval = 40;
       }
       // When a new SelectedIndexChanged event arrives, disable, then enable the
       // timer, effectively resetting it, so that after the last one in a batch
       // arrives, there is at least 40 ms before we react, plenty of time 
       // to wait any other selection events in the same batch.
       m_changeDelayTimer.Enabled = false;
       m_changeDelayTimer.Enabled = true;
    }

    private void ChangeDelayTimerTick(object sender, EventArgs e)
    {
       m_changeDelayTimer.Enabled = false;
       base.OnSelectedIndexChanged(new EventArgs());
    }
 }

請讓我知道這是否可以改進。

引用自:https://stackoverflow.com/questions/86793