【问题标题】:C# Implementing Auto-Scroll in a ListView while Drag & DroppingC#在拖放时在ListView中实现自动滚动
【发布时间】:2010-10-14 05:23:09
【问题描述】:

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

【问题讨论】:

    标签: c# winforms listview drag-and-drop scroll


    【解决方案1】:

    感谢您的链接 (http://www.knowdotnet.com/articles/listviewdragdropscroll.html),我已经 C#化了它

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

    【讨论】:

    • George Polevoy 的回答比这简单得多
    【解决方案2】:

    可以使用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();
        }
    }
    

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

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

    【讨论】:

    • 一旦你得到一个非空项目,你可以总是调用 item.EnsureVisible()。如果需要滚动,它将执行此操作,否则它什么也不做。
    • 我不明白。这里的想法是对您拖动的项目旁边的项目进行 InsureVisible 调用。
    • 您可以在检查项目不为空后使用 item.EnsureVisible() 并避免获取 index、maxIndex、scrollZoneHeight 等。用户必须在顶部或底部边缘多拖动一点,但它作品。如果您希望用户仅将鼠标悬停在第一个或最后一个项目上即可滚动,那么是的,您的代码是完美的。
    • 两个更正。 var maxIndex = listView.Items.Count - 1 可避免在向下滚动时在最后一项崩溃,而 var scrollZoneHeight = listView.Font.Height * 2 可扩大滚动开始的范围。然后竖起大拇指。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      只是给未来的谷歌员工的注意事项:要让它在更复杂的控件(例如 DataGridView)上工作,请参阅this thread

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多