views:

1042

answers:

4

The ListView doesn't seem to support the Scroll event. I need to call a function whenever the list is scrolled; how would I go about that?

A: 

You need to override the original ListView, look here:

http://www.vbforums.com/showthread.php?t=365804

It's not so straight forward maybe, but as i often say, maybe you should think about re-designing? :)

Filip Ekberg
A: 

Here's a solution that respects each of the ListView's display modes:

We rely on the fact that as the ListView is scrolled, the position of the items change. If we check for a change in the first ListViewItem's Bounds property, we can track whether movement has occurred.

You'll need to add a Timer control to the same form your ListView is on and set its Enabled property to True (this means that it will fire regularly without having to be Started). Also add a private variable to your form class to record the first item's Bounds.

private Rectangle _firstItemBounds = null;

When you populate your ListView, set this variable to the first item's Bounds. For example:

private void Form1_Load(object sender, EventArgs e)
{
    for (int i = 0; i < 1000; i++)
    {
        listView1.Items.Add(new ListViewItem("Item " + i));
    }

    _firstItemBounds = listView1.Items[0].Bounds;
}

Then add a handler for the Timer's Tick event:

private void timer1_Tick(object sender, EventArgs e)
{
    if (listView1.Items[0] == null)
    {
        return;
    }

    Rectangle bounds = listView1.Items[0].Bounds;

    if (bounds != _firstItemBounds)
    {
        _firstItemBounds = bounds;

        // Any scroll logic here
        // ...
    }
}

The default Timer Interval of 100ms seems to work fine for me, but you may need to tweak this to suit your application.

I hope this helps.

Dave R.
+4  A: 

Why do you need to call a function when the list is scrolled?

If you are changing the items as it's scrolled i would recommend setting the listview to virtual.

Or you could override the listview and do this:

public class TestListView : System.Windows.Forms.ListView
{
    private const int WM_HSCROLL = 0x114;
    private const int WM_VSCROLL = 0x115;
    public event EventHandler Scroll;

    protected void OnScroll()
    {

        if (this.Scroll != null)
            this.Scroll(this, EventArgs.Empty);

    }

    protected override void WndProc(ref System.Windows.Forms.Message m)
    {
        base.WndProc(ref m);
        if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL)
            this.OnScroll();
    }
}
Brian Rudolph
A: 

it seems the best approach is the brian's solution. However, its only responds to events generated by scrollbars, but no to events from mouse midbuttton.

if you change the conditional:

   if (m.Msg == WM_HSCROLL || m.Msg == WM_VSCROLL) 
             this.OnScroll();

by:

   if (m.Msg == 0x000c2c9) 
             this.OnScroll();

now it respods at all scrolling events in listview.

keimacias