【问题标题】:Handling scroll event on listview in c#在 C# 中处理 listview 上的滚动事件
【发布时间】:2009-12-05 08:51:22
【问题描述】:

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

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

【问题讨论】:

    标签: c# listview event-handling scroll


    【解决方案1】:

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

    【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 不处理鼠标滚轮滚动。必须使用滚动条。如果需要,需要添加private const uint WM_MOUSEWHEEL = 0x020A;
    【解决方案3】:

    看到这个帖子ListView Scroll Event

    使用原生窗口类监听 对于滚动消息 列表框。可与任何控件一起使用。

    【讨论】:

    【解决方案4】:

    现在在 .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)
        {
            ...
        }
    

    【讨论】:

    • 这适用于 WPF。有用的信息,但问题是针对 Windows 窗体的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多