C#在拖放时在ListView中实现自动滚动

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/660663/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 12:18:11  来源:igfitidea点击:

C# Implementing Auto-Scroll in a ListView while Drag & Dropping

c#winformslistviewdrag-and-dropscroll

提问by David Hayes

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

如何在 Winforms ListView 中实现自动滚动(例如,当您靠近顶部或底部时,ListView 会滚动)?我在谷歌上四处寻找,但运气不佳。我不敢相信这不是开箱即用的!预先感谢戴夫

采纳答案by George Polevoy

Scrolling can be accomplished with the ListViewItem.EnsureVisiblemethod. 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.

可以使用ListViewItem.EnsureVisible方法完成滚动。您需要确定您当前拖动的项目是否位于列表视图的可见边界,而不是第一个/最后一个。

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.

然后将此方法连接到 DragOver 事件。

targetListView.DragOver += RevealMoreItems;

targetListView.DragOver += (sender, e) =>
{
    e.Effect = DragDropEffects.Move;
};

回答by David Hayes

Thanks for the link (http://www.knowdotnet.com/articles/listviewdragdropscroll.html), I C#ised it

感谢您的链接(http://www.knowdotnet.com/articles/listviewdragdropscroll.html),IC#ISED它

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);
    }
}

回答by Grammarian

Have a look at ObjectListView. It does this stuff. You can read the code and use that if you don't want to use the ObjectListView itself.

看看ObjectListView。它做这件事。如果您不想使用 ObjectListView 本身,您可以阅读代码并使用它。

回答by BlueRaja - Danny Pflughoeft

Just a note for future googlers: to get this working on more complex controls (such as DataGridView), see this thread.

只是给未来的 googlers 一个注意事项:要使其在更复杂的控件(例如 DataGridView)上工作,请参阅此线程