2009-03-19 2 views
4

Как реализовать автоматическую прокрутку (например, ListView прокручивает, когда вы приближаетесь к вершине или внизу) в ListView ListView? Я охотился на Google с небольшой удачей. Я не могу поверить, что это не работает из коробки! Заранее спасибо DaveC# Внедрение автоматического прокрутки в ListView при перетаскивании и удалении

ответ

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; 
}; 
+0

Как только вы получите ненулевой элемент, вы всегда можете вызвать item.EnsureVisible(). Если требуется прокрутка, он сделает это, и в противном случае он ничего не сделает. –

+0

Я не понимаю. Идея здесь - вызов InsureVisible для элемента рядом с тем, который вы перетаскиваете. –

+0

Вы можете использовать item.EnsureVisible() после проверки того, что элемент не является нулевым и избегать получения индекса, maxIndex, scrollZoneHeight и т. Д. Пользователь должен перетащить немного больше по верхнему или нижнему краю, но он работает. Если вы хотите, чтобы пользователь получал прокрутку, только зависающую над первым или последним элементом, то да, ваш код идеально подходит. –

8

Спасибо за ссылку (http://www.knowdotnet.com/articles/listviewdragdropscroll.html), I 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); 
    } 
} 
+0

Я использовал тот же код, но его не работает для меня, почему? – Ram

+0

Ответ Джорджа Полевого намного проще, чем этот –

2

Посмотрите ObjectListView. Он делает это. Вы можете прочитать код и использовать его, если вы не хотите использовать ObjectListView.

0

Только примечание для будущих гуглеров: чтобы эта работа работала над более сложными элементами управления (такими как DataGridView), см. this thread.

Смежные вопросы