views:

1109

answers:

3

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?

A: 

See this post ListView Scroll Event

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

astander
+3  A: 

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.

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:

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;
}
Hans Passant
thanks a lot nobugz. this is exactly what i'm trying to achieve.
murasaki5
Read http://stackoverflow.com/questions/1176703/listview-onscroll-event/1182232#1182232 to see some limits with the WM_VSCROLL message.
Grammarian
A: 

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

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

        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:

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