如何避免数千个不必要的 ListView.SelectedIndexChanged 事件? [英] How to avoid thousands of needless ListView.SelectedIndexChanged events?

查看:12
本文介绍了如何避免数千个不必要的 ListView.SelectedIndexChanged 事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果用户选择 .NET 2.0 ListView 中的所有项目,ListView 将为每个项目触发一个 SelectedIndexChanged 事件,而不是触发一个事件来指示 选择 变了.

If a user select all items in a .NET 2.0 ListView, the ListView will fire a SelectedIndexChanged event for every item, rather than firing an event to indicate that the selection has changed.

如果用户然后单击以仅选择列表中的一个项目,ListView 将为 每个 未选择的项目触发 SelectedIndexChanged 事件,然后 SelectedIndexChanged 事件strong>SelectedIndexChanged 事件用于单个新选择的项目,而不是触发事件以指示选择已更改.

If the user then clicks to select just one item in the list, the ListView will fire a SelectedIndexChanged event for every item that is getting unselected, and then an SelectedIndexChanged event for the single newly selected item, rather than firing an event to indicate that the selection has changed.

如果您在 SelectedIndexChanged 事件处理程序中有代码,当您开始在列表中有几百/几千个项目时,程序将变得非常无响应.

If you have code in the SelectedIndexChanged event handler, the program will become pretty unresponsive when you begin to have a few hundred/thousand items in the list.

我考虑过停留定时器

但是有没有人有一个很好的解决方案来避免成千上万个不必要的 ListView.SelectedIndexChange 事件,当真正一个事件可以做到的时候?

But does anyone have a good solution to avoid thousands of needless ListView.SelectedIndexChange events, when really one event will do?

推荐答案

来自 Ian 的好解决方案.我把它变成了一个可重用的类,确保正确处理计时器.我还减少了获得响应速度更快的应用程序的间隔.此控件还双重缓冲以减少闪烁.

Good solution from Ian. I took that and made it into a reusable class, making sure to dispose of the timer properly. I also reduced the interval to get a more responsive app. This control also doublebuffers to reduce flicker.

  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());
     }
  }

请告诉我是否可以改进.

Do let me know if this can be improved.

这篇关于如何避免数千个不必要的 ListView.SelectedIndexChanged 事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆