How do I implement Auto-Scrolling (e.g. the ListView scrolls when you near the top or bottom) in a Winforms ListView? I've hunted around on google with little luck. I can't believe this doesn't work out of the box! Thanks in advance Dave
Thanks for the link (http://www.knowdotnet.com/articles/listviewdragdropscroll.html), I C#ised it
class ListViewBase:ListView
{
private Timer tmrLVScroll;
private System.ComponentModel.IContainer components;
private int mintScrollDirection;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
const int WM_VSCROLL = 277; // Vertical scroll
const int SB_LINEUP = 0; // Scrolls one line up
const int SB_LINEDOWN = 1; // Scrolls one line down
public ListViewBase()
{
InitializeComponent();
}
protected void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.tmrLVScroll = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// tmrLVScroll
//
this.tmrLVScroll.Tick += new System.EventHandler(this.tmrLVScroll_Tick);
//
// ListViewBase
//
this.DragOver += new System.Windows.Forms.DragEventHandler(this.ListViewBase_DragOver);
this.ResumeLayout(false);
}
protected void ListViewBase_DragOver(object sender, DragEventArgs e)
{
Point position = PointToClient(new Point(e.X, e.Y));
if (position.Y <= (Font.Height / 2))
{
// getting close to top, ensure previous item is visible
mintScrollDirection = SB_LINEUP;
tmrLVScroll.Enabled = true;
}else if (position.Y >= ClientSize.Height - Font.Height / 2)
{
// getting close to bottom, ensure next item is visible
mintScrollDirection = SB_LINEDOWN;
tmrLVScroll.Enabled = true;
}else{
tmrLVScroll.Enabled = false;
}
}
private void tmrLVScroll_Tick(object sender, EventArgs e)
{
SendMessage(Handle, WM_VSCROLL, (IntPtr)mintScrollDirection, IntPtr.Zero);
}
}
Scrolling can be accomplished with the ListViewItem.EnsureVisible method. You need to determine if the item you are currently dragging over is at the visible boundary of the list view and is not the first/last.
private static void RevealMoreItems(object sender, DragEventArgs e)
{
var listView = (ListView)sender;
var point = listView.PointToClient(new Point(e.X, e.Y));
var item = listView.GetItemAt(point.X, point.Y);
if (item == null)
return;
var index = item.Index;
var maxIndex = listView.Items.Count;
var scrollZoneHeight = listView.Font.Height;
if (index > 0 && point.Y < scrollZoneHeight)
{
listView.Items[index - 1].EnsureVisible();
}
else if (index < maxIndex && point.Y > listView.Height - scrollZoneHeight)
{
listView.Items[index + 1].EnsureVisible();
}
}
Then wire this method to the DragOver event.
targetListView.DragOver += RevealMoreItems;
targetListView.DragOver += (sender, e) =>
{
e.Effect = DragDropEffects.Move;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With