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 el MouseDown, vamos a registrar la posición actual del ratón, lo que vamos a utilizar como punto de relativa para determinar la dirección en que se desplazan en. En el movimiento del ratón, vamos a obtener el componente ScrollViwer de ListView y luego Desplácese 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 carece ya que es sólo una prueba de concepto, pero definitivamente debe empezar 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.
Gracias Pop. ¿Qué es la virtualización? –
La virtualización es donde el contenido dentro de un VirtualizingStackPanel (que es el Panel de elementos predeterminado para ListBoxs y tal) no representa el diseño de los elementos hasta/a menos que el elemento sea visible. Por lo tanto, con numerosos elementos o visualmente complejos, puede ofrecer un impulso significativo en el rendimiento, ya que solo genera la interfaz de usuario para un pequeño porcentaje a la vez. Más información aquí: http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx – rmoore
Haciendo esto está cambiando de desplazamiento lógico a físico (suponiendo que está utilizando un StackPanel que implementa IScrollInfo). Si todavía desea el desplazamiento lógico, pero para hacerlo sin problemas, esto no ayuda – Schneider