Handling scroll event on listview in c#
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;
}
Based upon the post that @Adriaan Stander posted my class for raising scroll events is below.
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!