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 ScrollViewer
y 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 ListBoxItem
s 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 ScrollViewer
La plantilla utiliza un Grid
. Estas parecen ser sus opciones, en orden de menor a mejor:
- Cambie el estilo del
ListBox
no tener unScrollViewer
y usa tu rediseñadoScrollViewer
afuera deListBox
. Entonces también tendrías que forzar elListBox
para ser lo suficientemente alto como para mostrar todos los elementos en ese mismoStyle
y 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. - Cambie el estilo del
ListBox
y establecer elControlTemplate
usar unScrollViewer
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 unVirtualizingStackPanel
, yay), pero como dijiste, necesita ser consciente de eso en tuDataTemplate
. - 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.