2009-12-05 10 views
12

Tengo una vista de lista que genera una miniatura usando un backgroundworker. Cuando se está desplazando la vista de lista, quiero pausar al trabajador de fondo y obtener el valor actual del área desplazada, cuando el usuario dejó de desplazarse por la vista de lista, reanudar el trabajo en segundo plano comenzando por el elemento de acuerdo con el valor del área desplazada.Manejo del evento de desplazamiento en la vista de lista en C#

¿Es posible manejar el evento scroll de una vista de lista? Si es así, ¿cómo? si no, ¿cuál es una buena alternativa de acuerdo con lo que describí anteriormente?

Respuesta

16

Tendrá que agregar compatibilidad con la clase ListView para que pueda recibir notificaciones sobre los eventos de desplazamiento. Agregue una nueva clase a su proyecto y pegue el siguiente código. Compilar. Coloque el nuevo control de vista de lista desde la parte superior de la caja de herramientas en su formulario. Implemente un controlador para el nuevo evento 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)); 
     } 
     } 
    } 

Tenga en cuenta que la posición de desplazamiento (ScrollEventArgs.NewValue) no es significativa, que depende del número de elementos en el ListView. Lo forcé a 0. A raíz de sus requisitos, desea ver la notificación ScrollEventType.EndScroll para saber cuándo el usuario dejó de desplazarse. Cualquier otra cosa te ayuda a detectar que el usuario comenzó a desplazarse. Por ejemplo:

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

muchas gracias nobugz. esto es exactamente lo que estoy tratando de lograr. – murasaki5

+3

Lea http://stackoverflow.com/questions/1176703/listview-onscroll-event/1182232#1182232 para ver algunos límites con el mensaje WM_VSCROLL. – Grammarian

+0

esta respuesta ha resuelto un error desagradable en net framework 2.0 con gridlines – Mandrake

1

Ver este post ListView Scroll Event

Usar la clase de ventana nativa para escuchar para los mensajes de desplazamiento en el cuadro de lista . Funcionará con cualquier control.

+0

Basado en la publicación que @Adriaan Stander publicó mi clase para subir eventos de desplazamiento está a continuación. http://stackoverflow.com/a/35645892/254215 – Dib

0

Cogiendo el evento de desplazamiento ahora se hace fácilmente en .NET 4.

capturar el evento carga desde el ListView (m_ListView) y hacer esto:

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

entonces, implementar su función ScrollViewer_ScrollChanged:

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

Esto es para WPF. Información útil, pero la pregunta es para formularios de Windows. – flobadob

0

Basado en la publicación que @Adriaan Stander poste d mi clase para subir eventos de desplazamiento está abajo.

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

Se usa como tal ...

Declarar un campo:

private ControlScrollListener _processListViewScrollListener; 

instanciarlo con los controles que usted necesita saber issrolling:

_processListViewScrollListener = new ControlScrollListener(ProcessesListView); 

alambre de un controlador:

_processListViewScrollListener.ControlScrolled += ProcessListViewScrollListener_ControlScrolled; 

Handler caso:

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

Los argumentos de eventos en el caso planteado podría ser ajustado para contener la información más útil. ¡Solo necesitaba saber que mi control había sido desplazado!

+0

No maneja la rueda del mouse. Tienes que usar la barra de desplazamiento. Necesitará agregar 'constintividad privada WM_MOUSEWHEEL = 0x020A;' si así lo desea. – rism

Cuestiones relacionadas