Saltar al contenido

Poner ListBox en ScrollViewer: la rueda del mouse no funciona

Solución:

En primer lugar, creo que debe detallar cuáles son sus limitaciones y qué está 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 sobre cómo obtener el resultado que busca.

Si pones ListBox dentro de una ScrollViewer, luego la plantilla de control para ListBox todavía tiene lo suyo ScrollViewer dentro. Cuando el cursor del mouse está sobre el ListBox y desplaza la rueda del mouse, ese evento burbujea hasta que alcanza el ScrollViewer eso es parte de ListBox. Ese lo maneja desplazándose y marca el evento como manejado, entonces el ScrollViewer tu pones el ListBox dentro de ignora el evento.

Si haces el ListBox más alto y más estrecho que el exterior ScrollViewery dele suficientes elementos para que el ListBox mismo puede desplazar los elementos, verá 2 barras de desplazamiento verticales: 1 en el ListBox, y 1 fuera del ListBox para tu exterior ScrollViewer. Cuando el cursor del mouse está dentro del ListBox, los ListBox desplazará los elementos con su interior ScrollViewer, y es Border permanecerá en su lugar. Cuando el cursor del mouse está fuera del ListBox y dentro del exterior ScrollViewer, ese ScrollViewer desplazará su contenido – el ListBox – que puede verificar si nota que el ListBox‘s Border cambia de posición.

Si quieres un exterior ScrollViewer para desplazarse por todo ListBox control (incluido el Border y no solo los elementos), tendrá que cambiar el estilo del ListBox para que no tenga un interno ScrollViewer, pero también deberá asegurarse de que aumente automáticamente de acuerdo con sus elementos.

No recomiendo este enfoque por un par de razones. Podría tener sentido si hay otros controles dentro del ScrollViewer junto con ListBox, pero su muestra no lo indica. Además, si va a tener muchos elementos en el ListBox, estarás creando ListBoxItems para cada uno, eliminando cualquier ventaja que el predeterminado, no rediseñado ListBox te da por defecto VirtualizingStackPanel.

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


Editar: Ok, ahora tengo una idea un poco mejor, con la adición de esas imágenes. El efecto que está obteniendo es que cuando hay suficientes elementos para desplazarse y aparece la barra de desplazamiento, el área disponible tiene que encogerse un poco horizontalmente porque el ScrollViewerLa plantilla utiliza un Grid. Estas parecen ser sus opciones, en orden de menor a mejor:

  1. Cambie el estilo del ListBox no tener un ScrollViewer y usa tu rediseñado ScrollViewer afuera de ListBox. Entonces también tendrías que forzar el ListBox para ser lo suficientemente alto como para mostrar todos los elementos en ese mismo Styley ahora ha perdido la virtualización de la interfaz de usuario. Si va a mostrar cientos de elementos en la lista, definitivamente no quiero perder eso.
  2. Cambie el estilo del ListBox y establecer el ControlTemplate usar un ScrollViewer con el estilo que ya creó para él que coloca la barra de desplazamiento sobre el contenido en lugar de en una columna separada. Este está bienListBox llega a limitar su altura y usa un VirtualizingStackPanel, yay), pero como dijiste, necesita ser consciente de eso en tu DataTemplate.
  3. Cambie el estilo del ScrollViewer para dejar espacio para la barra de desplazamiento vertical incluso cuando no está visible. Así es como se ve esta opción:

Por defecto, ScrollViewer usa 2 columnas en una Grid equivalente a esto:

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

Entonces el 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á oculta, vinculamos el 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>

Entonces ahora el ControlTemplate en la costumbre Style por ScrollViewer podría verse así:

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

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

Probablemente querrás ver el resto del ejemplo. ControlTemplate por ScrollViewer, pero esos ejemplos no son los estilos predeterminados. ¡Tenga en cuenta que el ejemplo coloca la barra de desplazamiento vertical a la izquierda! También tenga en cuenta el comentario en la parte inferior sobre ContentScrollPresenter.

Estaba lidiando con el mismo problema. Yo configuro el ListBox.ItemsPanel Propiedad, sin ninguna 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *