在 C# 中处理列表视图上的滚动事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1851620/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 21:23:18  来源:igfitidea点击:

Handling scroll event on listview in c#

c#listviewevent-handlingscroll

提问by murasaki5

I have a listview that generates thumbnail using a backgroundworker. When the listview is being scrolled i want to pause the backgroundworker and get the current value of the scrolled area, when the user stopped scrolling the listview, resume the backgroundworker starting from the item according to the value of the scrolled area.

我有一个使用后台工作者生成缩略图的列表视图。当列表视图正在滚动时,我想暂停后台工作人员并获取滚动区域的当前值,当用户停止滚动列表视图时,根据滚动区域的值从项目开始恢复后台工作人员。

Is it possible to handle scroll event of a listview? if yes how? if not then what is a good alternative according to what i described above?

是否可以处理列表视图的滚动事件?如果是,如何?如果不是,那么根据我上面的描述,什么是好的选择?

采纳答案by Hans Passant

You'll have to add support to the ListView class so you can be notified about scroll events. Add a new class to your project and paste the code below. Compile. Drop the new listview control from the top of the toolbox onto your form. Implement a handler for the new Scroll event.

您必须添加对 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));
        }
      }
    }

Beware that the scroll position (ScrollEventArgs.NewValue) isn't meaningful, it depends on the number of items in the ListView. I forced it to 0. Following your requirements, you want to watch for the ScrollEventType.EndScroll notification to know when the user stopped scrolling. Anything else helps you detect that the user started scrolling. For example:

请注意滚动位置 (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;
}

回答by Adriaan Stander

See this post ListView Scroll Event

看这个帖子ListView 滚动事件

Use the native window class to listen for the scroll messages on the listbox. Will work with any control.

使用本机窗口类来侦听列表框上的滚动消息。将与任何控件一起使用。

回答by metao

Catching the scroll event now is easily done in .net 4.

现在在 .net 4 中很容易捕获滚动事件。

Catch the Loaded event from your ListView (m_ListView) and do this:

从 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;
        }

then, implement your ScrollViewer_ScrollChanged function:

然后,实现你的 ScrollViewer_ScrollChanged 函数:

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

回答by Dib

Based upon the post that @Adriaan Stander posted my class for raising scroll events is below.

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

Use it like so...

像这样使用它......

Declare a field:

声明一个字段:

 private ControlScrollListener _processListViewScrollListener;

Instantiate it with the controls which you need to know issrolling:

使用您需要知道的滚动控件实例化它:

_processListViewScrollListener = new ControlScrollListener(ProcessesListView);

Wire in a handler:

在处理程序中接线:

_processListViewScrollListener.ControlScrolled += ProcessListViewScrollListener_ControlScrolled;

Handler the event:

处理事件:

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

The event args in the event raised could be tweaked to contain more useful information. I just needed to know my control had been scrolled!

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