2009-08-18 49 views
5

Mi rueda del mouse no funciona al poner un ListBox en un ScrollViewer.Poner ListBox en ScrollViewer: la rueda del mouse no funciona

¿El ListBox de alguna manera "roba" este evento?

<ScrollViewer VerticalScrollBarVisibility="Auto" Style="{StaticResource myStyle}"> 
<ListBox> 
    <ListBoxItem>Test 1</ListBoxItem> 
    <ListBoxItem>Test 2</ListBoxItem> 
    <ListBoxItem>Test 3</ListBoxItem> 
    <ListBoxItem>Test 4</ListBoxItem> 
    <ListBoxItem>Test 5</ListBoxItem> 
    <ListBoxItem>Test 6</ListBoxItem> 
    <ListBoxItem>Test 7</ListBoxItem> 
</ListBox> 
</ScrollViewer> 

Editar: conforme a lo solicitado por Joel, agregó la razón por la que hice esto .. he hecho porque no me gusta lo que el ListBox 's interna ScrollViewer hace con mi diseño. Tengo una imagen de fondo, y encima de eso una ListBox como se muestra aquí:

alt text http://robbertdam.nl/share/1.png

Ahora, cuando aparece la barra de desplazamiento, ocurre lo siguiente:

alt text http://robbertdam.nl/share/2.png

He creado una Estilo para un ScrollViewer que muestra la barra de desplazamiento en la parte superior del contenido del elemento ListBox. En el datatemplate del elemento ListBox, he reservado un espacio para que aparezca la barra de desplazamiento.

Gracias, Robbert presa

Respuesta

15

En primer lugar, creo que es necesario dar más detalles sobre cuáles son tus limitaciones y lo que estamos tratando de lograr. Sin eso, solo puedo explicar por qué lo que estás haciendo no está funcionando. Alguien puede incluso tener una mejor idea acerca de cómo obtener el resultado que busca.

Si coloca dentro de un ListBoxScrollViewer, entonces el control template para ListBox todavía tiene su propia ScrollViewer interior. Cuando el cursor del mouse está sobre el ListBox y se desplaza la rueda del mouse, ese evento aparece hasta que llega al ScrollViewer que forma parte de ListBox. Eso lo maneja desplazándose y marca el evento como manejado, entonces el ScrollViewer en el que coloca el ListBox ignora el evento.

Si usted hace la ListBox más alto y más estrecho que el exterior ScrollViewer, y darle suficientes elementos para que el ListBox sí mismo puede desplazarse los artículos, verá 2 barras de desplazamiento vertical: 1 en el ListBox y 1 fuera de la ListBox para su exterior ScrollViewer. Cuando el cursor del mouse esté dentro del ListBox, el ListBox desplazará los elementos con su ScrollViewer interno, y su Border permanecerá en su lugar. Cuando el cursor del mouse está fuera del ListBox y dentro del exterior ScrollViewer, ese ScrollViewer desplazará su contenido - ListBox - que puede verificar al observar que ListBox 's Border cambia de posición.

Si desea una combinación externa ScrollViewer para desplazarse todo el ListBox de control (incluyendo los Border y no sólo los artículos), tendrá que volver al estilo de la ListBox de modo que no tiene un interior ScrollViewer, pero' También será necesario asegurarse de que aumente automáticamente de acuerdo con sus artículos.

No recomiendo este enfoque por un par de razones.Puede tener sentido si hay otros controles dentro del ScrollViewer junto con el ListBox, pero su muestra no lo indica. Además, si va a tener muchos elementos en el ListBox, creará ListBoxItem s para cada uno, eliminando cualquier ventaja que le brinde el ListBox predeterminado, sin cambiar el estilo, debido al VirtualizingStackPanel predeterminado.

Háganos saber cuáles son sus necesidades reales.


Editar: Ok, ahora tengo un poco mejor idea, con la adición de esas imágenes. El efecto que obtiene es que cuando hay suficientes elementos para desplazarse y aparece la barra de desplazamiento, el área disponible debe reducirse un poco horizontalmente porque la plantilla ScrollViewer usa un Grid. Estas parecen ser las opciones, con el fin de menor a mayor: Re-estilo

  1. la ListBox que no tienen una ScrollViewer y usar su re-labrado ScrollViewer fuera del ListBox. También tendría que forzar el ListBox para que también sea lo suficientemente alto como para mostrar todos los elementos en el mismo Style, y ahora ha perdido la virtualización de la interfaz de usuario. Si va a mostrar cientos de artículos en la lista, usted definitivamente no quiere perder eso.
  2. Vuelva a diseñar el ListBox y configure ControlTemplate para usar un ScrollViewer con el estilo que ya creó para que coloque la barra de desplazamiento sobre el contenido en lugar de en una columna separada. Este está bien (ListBox llega a limitar su altura y usa un VirtualizingStackPanel, yay), pero como dijiste, necesita conocimiento de eso en tu DataTemplate.
  3. Vuelva a diseñar el ScrollViewer para dejar espacio para la barra de desplazamiento vertical, incluso cuando no esté visible. Esto es lo que se ve esta opción como:

Por defecto, ScrollViewer utiliza 2 columnas en un Grid equivalente a esto:

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    <ColumnDefinition Width="Auto" /> 
</Grid.ColumnDefinitions> 

Así que la Width de la columna de la barra de desplazamiento es 0 cuando la barra de desplazamiento no es visible desde Width="Auto". Para dejar espacio para la barra de desplazamiento, incluso cuando está oculto, nos atamos a la Width de esa columna a la Width de la barra de desplazamiento vertical:

<Grid.ColumnDefinitions> 
    <ColumnDefinition Width="*" /> 
    <ColumnDefinition 
     Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" /> 
</Grid.ColumnDefinitions> 

Así que ahora la ControlTemplate en la costumbre Style para ScrollViewer podría tener este aspecto:

<ControlTemplate 
    TargetType="{x:Type ScrollViewer}"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition /> 
      <ColumnDefinition 
       Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" /> 
     </Grid.ColumnDefinitions> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition 
       Height="Auto" /> 
     </Grid.RowDefinitions> 

     <ScrollContentPresenter /> 

     <ScrollBar 
      Grid.Column="1" 
      Name="PART_VerticalScrollBar" 
      Value="{TemplateBinding VerticalOffset}" 
      Maximum="{TemplateBinding ScrollableHeight}" 
      ViewportSize="{TemplateBinding ViewportHeight}" 
      Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" /> 
     <ScrollBar 
      Name="PART_HorizontalScrollBar" 
      Orientation="Horizontal" 
      Grid.Row="1" 
      Value="{TemplateBinding HorizontalOffset}" 
      Maximum="{TemplateBinding ScrollableWidth}" 
      ViewportSize="{TemplateBinding ViewportWidth}" 
      Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" /> 

    </Grid> 
</ControlTemplate> 

Usted podría incluso hacer la columna el contenido de un tamaño fijo y la columna de la barra de desplazamiento Width="*", lo que podría funcionar mejor en el largo plazo si su imagen no se estira. Ahora, el DataTemplate no tiene que compensar el ancho de una barra de desplazamiento, ya que tiene un área consistente para usar si la barra de desplazamiento está visible o no.

Probablemente querrá ver el resto de example ControlTemplate for ScrollViewer, pero esos ejemplos no son los estilos predeterminados. ¡Observe que el ejemplo pone la barra de desplazamiento vertical a la izquierda! También tenga en cuenta el comentario al final sobre ContentScrollPresenter.

+0

Actualizado mi publicación .. –

3

Estaba lidiando con el mismo problema. Me puse la ListBox.ItemsPanel propiedad, sin ningún ScrollViewer:

<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"> 
    <ListBox 
    <ListBox.Template> 
     <ControlTemplate TargetType="ItemsControl"> 
      <Border> 
       <ItemsPresenter /> 
      </Border> 
     </ControlTemplate> 
    </ListBox.Template> 
    <ListBox.ItemsPanel> 
     <ItemsPanelTemplate> 
      <VirtualizingStackPanel /> 
     </ItemsPanelTemplate> 
    </ListBox.ItemsPanel> 
    <\ListBox> 
<\ScrollViewer> 

Espero que esto ayude.

0

ver este enlace para obtener otra respuesta: Scroll in ScrollViewer when mouse over ListBox

Hola, creo que se puede controlar el evento PreviewMouseWheel la totalidad del cuadro de lista. Esto también afectará los elementos individuales, siempre y cuando no maneje cada artículo

PreviewMouseWheel and mark the event as handled: 
    private void ListBox_PreviewMouseWheel(object sender, MouseWheelEventArgs e) 
    { 
     if (e.Delta < 0) 
     { 
      scrollViewer1.LineDown(); 
     } 
     else 
     { 
      scrollViewer1.LineUp(); 
     } 
    } 
Cuestiones relacionadas