2009-12-05 2 views
12

У меня есть listview, который генерирует миниатюру с помощью фонаря. Когда прокрутка списка прокручивается, я хочу приостановить работу фонового рабочего и получить текущее значение прокрученной области, когда пользователь прекратил прокрутку списка, возобновите работу фонового рабочего, начиная с элемента, в соответствии со значением прокрученной области.Обработка прокрутки события в listview в C#

Возможно ли обработать событие прокрутки списка? если да, то как? если нет, то какая хорошая альтернатива в соответствии с тем, что я описал выше?

ответ

16

Вам нужно будет добавить поддержку класса ListView, чтобы вы могли получать уведомления о событиях прокрутки. Добавьте новый класс в свой проект и вставьте код ниже. Компиляция. Отбросьте новый элемент управления listview с верхней части панели инструментов на свою форму. Внедрите обработчик для нового события Scroll.

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

Имейте ввиду, что положение прокрутки (ScrollEventArgs.NewValue) не имеет смысла, это зависит от количества элементов в ListView. Я заставил его выполнить 0. Следуя вашим требованиям, вы хотите посмотреть уведомление ScrollEventType.EndScroll, чтобы узнать, когда пользователь прекратил прокрутку. Все остальное поможет вам обнаружить, что пользователь начал прокрутку. Например:

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

Большое спасибо nobugz. это именно то, чего я пытаюсь достичь. – murasaki5

+3

Прочтите http://stackoverflow.com/questions/1176703/listview-onscroll-event/1182232#1182232, чтобы увидеть некоторые ограничения с сообщением WM_VSCROLL. – Grammarian

+0

этот ответ разрешил неприятную ошибку на сетевом каркасе 2.0 с линиями сетки – Mandrake

1

Увидеть этот пост ListView Scroll Event

Использование родного класса окна для прослушивания для сообщений прокрутки на ListBox. Будет работать с любым контролем.

+0

Основываясь на сообщении, которое @Adriaan Stander опубликовал мой класс для поднятия событий прокрутки, приведен ниже. http://stackoverflow.com/a/35645892/254215 – Dib

0

Поймать событие прокрутки теперь легко сделать в .net 4.

Поймать Loaded события из вашего ListView (m_ListView) и сделать это:

 if (VisualTreeHelper.GetChildrenCount(m_ListView) != 0) 
     { 
      Decorator border = VisualTreeHelper.GetChild(m_ListView, 0) as Decorator; 
      ScrollViewer sv = border.Child as ScrollViewer; 
      sv.ScrollChanged += ScrollViewer_ScrollChanged; 
     } 

тогда, выполните вашу функцию ScrollViewer_ScrollChanged:

private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     ... 
    } 
+1

Это для WPF. Полезная информация, но вопрос о формах окон. – flobadob

0

Основано на сообщении, что @Adriaan Stander poste d мой класс для создания событий прокрутки приведен ниже.

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

Используйте его как так ...

Объявляем поле:

private ControlScrollListener _processListViewScrollListener; 

инстанцируйте его с контроля, которые вы должны знать issrolling:

_processListViewScrollListener = new ControlScrollListener(ProcessesListView); 

провода в обработчик:

_processListViewScrollListener.ControlScrolled += ProcessListViewScrollListener_ControlScrolled; 

Обработчик события:

void ProcessListViewScrollListener_ControlScrolled(object sender, EventArgs e) 
{ 
    // do what you need to do 
} 

В арг событий в случае поднятого может быть переделаны, чтобы содержать больше полезной информации. Мне просто нужно было знать, что мой контроль был прокручен!

+0

Не обрабатывает прокрутку колесика мыши. Необходимо использовать полосу прокрутки. Нужно добавить 'private const uint WM_MOUSEWHEEL = 0x020A;' если вы этого хотите. – rism

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