c# .net wpf listview scroll

c# - ¿Es posible implementar desplazamiento suave en una vista de lista de WPF?



.net listview (5)

¿Es posible implementar desplazamiento suave en una lista de WPF como funciona en Firefox?
Cuando el navegador Firefox contenía todos los elementos de la vista de lista y mantienes presionado el botón central del mouse (pero no el lanzamiento), y lo arrastras, debería desplazar suavemente los elementos de la vista de lista. Cuando lo suelte, debería detenerse.

Parece que esto no es posible en winforms, pero me pregunto si está disponible en WPF.


De hecho, es posible hacer lo que está pidiendo, aunque requerirá una buena cantidad de código personalizado.

Normalmente, en WPF, ScrollViewer utiliza lo que se conoce como Desplazamiento lógico, lo que significa que se desplazará elemento por elemento en lugar de desplazarse. Las otras respuestas cubren algunas de las formas en que puede cambiar el comportamiento del Desplazamiento lógico al de Desplazamiento físico. La otra forma es hacer uso de los métodos ScrollToVertialOffset y ScrollToHorizontalOffset expuestos tanto por ScrollViwer como por IScrollInfo.

Para implementar la parte más grande, el desplazamiento cuando se presiona la rueda del mouse, necesitaremos hacer uso de los eventos MouseDown y MouseMove.

<ListView x:Name="uiListView" Mouse.MouseDown="OnListViewMouseDown" Mouse.MouseMove="OnListViewMouseMove" ScrollViewer.CanContentScroll="False"> .... </ListView>

En MouseDown, vamos a registrar la posición actual del mouse, que usaremos como un punto relativo para determinar en qué dirección nos desplazamos. Con el movimiento del mouse, obtendremos el componente ScrollViwer de ListView y luego lo desplazaremos en consecuencia.

private Point myMousePlacementPoint; private void OnListViewMouseDown(object sender, MouseButtonEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed) { myMousePlacementPoint = this.PointToScreen(Mouse.GetPosition(this)); } } private void OnListViewMouseMove(object sender, MouseEventArgs e) { ScrollViewer scrollViewer = ScrollHelper.GetScrollViewer(uiListView) as ScrollViewer; if (e.MiddleButton == MouseButtonState.Pressed) { var currentPoint = this.PointToScreen(Mouse.GetPosition(this)); if (currentPoint.Y < myMousePlacementPoint.Y) { scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - 3); } else if (currentPoint.Y > myMousePlacementPoint.Y) { scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + 3); } if (currentPoint.X < myMousePlacementPoint.X) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset - 3); } else if (currentPoint.X > myMousePlacementPoint.X) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + 3); } } } public static DependencyObject GetScrollViewer(DependencyObject o) { // Return the DependencyObject if it is a ScrollViewer if (o is ScrollViewer) { return o; } for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) { var child = VisualTreeHelper.GetChild(o, i); var result = GetScrollViewer(child); if (result == null) { continue; } else { return result; } } return null; }

Hay algunas áreas que le faltan porque es solo una prueba de concepto, pero definitivamente debería ayudarlo a comenzar en la dirección correcta. Para hacer que se desplace constantemente una vez que el mouse se aleja del punto inicial MouseDown, la lógica de desplazamiento podría ir a un DispatcherTimer o algo similar.


Intente configurar la propiedad adjunta ScrollViewer.CanContentScroll en false en ListView . Pero como dijo Pop Catalin , pierdes virtualización de elementos, lo que significa que todos los elementos de la lista se cargan y completan a la vez, no cuando se necesita mostrar un conjunto de elementos, por lo que si la lista es enorme, podría causar un poco de memoria y problemas de desempeño.


Puedes lograr un desplazamiento suave pero pierdes la virtualización de los elementos, por lo que básicamente debes usar esta técnica solo si tienes pocos elementos en la lista:

Información aquí: Desplazamiento suave en Listbox

Has intentado configurar:

ScrollViewer.CanContentScroll="False"

en el cuadro de lista?

De esta manera, el desplazamiento es manejado por el panel en lugar del ListBox ... Sin embargo, usted perderá la virtualización, por lo que podría ser más lento si tiene mucho contenido.


Si usa .NET 4.5 (o 4.0 si está dispuesto a piratear un poco), entonces hay una respuesta aquí .


intente configurar la altura de la vista de lista como auto y envolverla en un visor de desplazamiento.

<ScrollViewer IsTabStop="True" VerticalScrollBarVisibility="Auto"> <ListView></ListView> </ScrollViewer>

No olvides mencionar la altura de ScrollViewer. Espero que esto ayude ...