wpf event-handling listbox scrollviewer mousewheel

wpf - ¿Elementos secundarios del scrollviewer que impiden el desplazamiento con la rueda del ratón?



event-handling listbox (4)

Especificar una Listbox para el Listbox que no incluye un ScrollViewer resuelve el problema. Vea esta respuesta y estas dos páginas de MSDN para obtener más información:

ControlTemplate

ListBox estilos y plantillas

Tengo problemas para que la rueda del mouse funcione en el siguiente XAML, que he simplificado para mayor claridad:

<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" CanContentScroll="False" > <Grid MouseDown="Editor_MouseDown" MouseUp="Editor_MouseUp" MouseMove="Editor_MouseMove" Focusable="False" > <Grid.Resources> <DataTemplate DataType="{x:Type local:DataFieldModel}" > <Grid Margin="0,2,2,2" > <TextBox Cursor="IBeam" MouseDown="TextBox_MouseDown" MouseUp="TextBox_MouseUp" MouseMove="TextBox_MouseMove" /> </Grid> </DataTemplate> </Grid.Resources> <ListBox x:Name="DataFieldListBox" ItemsSource="{Binding GetDataFields}" SelectionMode="Extended" Background="Transparent" Focusable="False" > <ListBox.ItemsPanel> <ItemsPanelTemplate> <Canvas /> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem" > <Setter Property="Canvas.Left" Value="{Binding dfX}" /> <Setter Property="Canvas.Top" Value="{Binding dfY}" /> </Style> </ListBox.ItemContainerStyle> </ListBox> </Grid> </ScrollViewer>

Visualmente, el resultado es un área de algún tamaño conocido en el que la lectura de DataField de una colección se puede representar con TextBox que tienen una posición, un tamaño, etc., arbitrarios. En los casos en que el "área" con estilo de ListBox es demasiado grande para mostrarlo todo a la vez, es posible el desplazamiento horizontal y vertical, pero solo con las barras de desplazamiento.

Para una mejor ergonomía y cordura, el desplazamiento de la rueda del mouse debería ser posible, y normalmente ScrollViewer lo manejaría automáticamente, pero el ListBox parece estar entregando esos eventos de tal manera que ScrollViewer principal nunca los ve. Hasta ahora solo he podido obtener el desplazamiento de la rueda trabajando con IsHitTestVisible=False para ListBox o la Grid principal, pero, por supuesto, ninguno de los eventos del ratón del elemento secundario funciona después de eso.

¿Qué puedo hacer para asegurarme de que el ScrollViewer vea los eventos de la rueda del mouse y conserve los demás para los elementos secundarios?

Edición: Me acabo de ListBox que ListBox tiene un ScrollViewer incorporado que probablemente está robando eventos de la rueda del ScrollViewer principal y que la especificación de una plantilla de control puede desactivarlo. Voy a actualizar esta pregunta si eso resuelve el problema.


Otra forma de implementar esto, es creando su propio ScrollViewer de esta manera:

public class MyScrollViewer : ScrollViewer { protected override void OnMouseWheel(MouseWheelEventArgs e) { var parentElement = Parent as UIElement; if (parentElement != null) { if ((e.Delta > 0 && VerticalOffset == 0) || (e.Delta < 0 && VerticalOffset == ScrollableHeight)) { e.Handled = true; var routedArgs = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta); routedArgs.RoutedEvent = UIElement.MouseWheelEvent; parentElement.RaiseEvent(routedArgs); } } base.OnMouseWheel(e); } }


Sé que es un poco tarde pero tengo otra solución que funcionó para mí. Cambié mi stackpanel / listbox para un itemscontrol / grid. No estoy seguro de por qué los eventos de desplazamiento funcionan correctamente, pero lo hacen en mi caso.

<ScrollViewer VerticalScrollBarVisibility="Auto" PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"> <StackPanel Orientation="Vertical"> <ListBox ItemsSource="{Binding DrillingConfigs}" Margin="0,5,0,0"> <ListBox.ItemTemplate> <DataTemplate>

convirtió

<ScrollViewer VerticalScrollBarVisibility="Auto" PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ItemsControl ItemsSource="{Binding DrillingConfigs}" Margin="0,5,0,0" Grid.Row="0"> <ItemsControl.ItemTemplate> <DataTemplate>


También puede crear un comportamiento y adjuntarlo al control principal (en el que los eventos de desplazamiento deberían crecer).

// Used on sub-controls of an expander to bubble the mouse wheel scroll event up public sealed class BubbleScrollEvent : Behavior<UIElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.PreviewMouseWheel += AssociatedObject_PreviewMouseWheel; } protected override void OnDetaching() { AssociatedObject.PreviewMouseWheel -= AssociatedObject_PreviewMouseWheel; base.OnDetaching(); } void AssociatedObject_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { e.Handled = true; var e2 = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta); e2.RoutedEvent = UIElement.MouseWheelEvent; AssociatedObject.RaiseEvent(e2); } } <SomePanel> <i:Interaction.Behaviors> <viewsCommon:BubbleScrollEvent /> </i:Interaction.Behaviors> </SomePanel>