在c#中处理listview上的滚动事件

时间:2009-12-05 08:51:23

标签: c# listview event-handling scroll

我有一个listview,可以使用backgroundworker生成缩略图。当滚动列表视图时,我想暂停背景工作并获得滚动区域的当前值,当用户停止滚动列表视图时,根据滚动区域的值从项目开始恢复背景工作。

是否可以处理列表视图的滚动事件?如果有,怎么样?如果没有,那么根据我上面描述的内容,什么是一个好的选择呢?

4 个答案:

答案 0 :(得分:19)

您必须添加对ListView类的支持,以便您可以收到有关滚动事件的通知。在项目中添加一个新类并粘贴下面的代码。编译。将新的listview控件从工具箱顶部拖放到表单上。为新的Scroll事件实现处理程序。

using System;
using System.Windows.Forms;

    class MyListView : ListView {
      public event ScrollEventHandler Scroll;
      protected virtual void OnScroll(ScrollEventArgs e) {
        ScrollEventHandler handler = this.Scroll;
        if (handler != null) handler(this, e);
      }
      protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        if (m.Msg == 0x115) { // Trap WM_VSCROLL
          OnScroll(new ScrollEventArgs((ScrollEventType)(m.WParam.ToInt32() & 0xffff), 0));
        }
      }
    }

请注意滚动位置(ScrollEventArgs.NewValue)没有意义,它取决于ListView中的项目数。我强制它为0.根据您的要求,您希望查看ScrollEventType.EndScroll通知以了解用户何时停止滚动。其他任何东西都可以帮助您检测用户是否开始滚动。例如:

ScrollEventType mLastScroll = ScrollEventType.EndScroll;

private void myListView1_Scroll(object sender, ScrollEventArgs e) {
  if (e.Type == ScrollEventType.EndScroll) scrollEnded();
  else if (mLastScroll == ScrollEventType.EndScroll) scrollStarted();
  mLastScroll = e.Type;
}

答案 1 :(得分:1)

请参阅此帖子ListView Scroll Event

  

使用本机窗口类进行侦听   对于滚动消息   列表框。可以使用任何控件。

答案 2 :(得分:0)

现在可以在.net 4中轻松捕捉滚动事件。

从ListView(m_ListView)中捕获Loaded事件并执行以下操作:

        if (VisualTreeHelper.GetChildrenCount(m_ListView) != 0)
        {
            Decorator border = VisualTreeHelper.GetChild(m_ListView, 0) as Decorator;
            ScrollViewer sv = border.Child as ScrollViewer;
            sv.ScrollChanged += ScrollViewer_ScrollChanged;
        }

然后,实现ScrollViewer_ScrollChanged函数:

    private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        ...
    }

答案 3 :(得分:0)

基于@Adriaan Stander发布的关于提升滚动事件的课程的帖子如下。

internal class ControlScrollListener : NativeWindow, IDisposable
{
    public event ControlScrolledEventHandler ControlScrolled;
    public delegate void ControlScrolledEventHandler(object sender, EventArgs e);

    private const uint WM_HSCROLL = 0x114;
    private const uint WM_VSCROLL = 0x115;
    private readonly Control _control;

    public ControlScrollListener(Control control)
    {
        _control = control;
        AssignHandle(control.Handle);
    }

    protected bool Disposed { get; set; }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (Disposed) return;

        if (disposing)
        {
            // Free other managed objects that implement IDisposable only
        }

        // release any unmanaged objects
        // set the object references to null
        ReleaseHandle();

        Disposed = true;
    }

    protected override void WndProc(ref Message m)
    {
        HandleControlScrollMessages(m);
        base.WndProc(ref m);
    }

    private void HandleControlScrollMessages(Message m)
    {
        if (m.Msg == WM_HSCROLL | m.Msg == WM_VSCROLL)
        {
            if (ControlScrolled != null)
            {
                ControlScrolled(_control, new EventArgs());
            }
        }
    }
}

像这样使用......

声明一个字段:

 private ControlScrollListener _processListViewScrollListener;

使用您需要知道的控件进行实例化:

_processListViewScrollListener = new ControlScrollListener(ProcessesListView);

连接处理程序:

_processListViewScrollListener.ControlScrolled += ProcessListViewScrollListener_ControlScrolled;

处理事件:

void ProcessListViewScrollListener_ControlScrolled(object sender, EventArgs e)
{
    // do what you need to do
}

可以调整所引发事件中的事件参数以包含更多有用信息。我只需要知道我的控件已经滚动了!