In primo luogo, penso che è necessario approfondire quali sono i vostri limiti sono e che cosa si sta cercando di raggiungere. Senza quello, posso solo spiegare perché quello che stai facendo non funziona. Qualcuno potrebbe anche avere un'idea migliore su come ottenere il risultato che stai cercando.
Se mettete ListBox
all'interno di un ScrollViewer
, allora la control template per ListBox
ha ancora il suo ScrollViewer
all'interno. Quando il puntatore del mouse si trova su ListBox
e si scorre la rotellina del mouse, l'evento bolle fino a raggiungere lo ScrollViewer
che fa parte di ListBox
. Quello lo gestisce scorrendo e segna l'evento come gestito, quindi lo ScrollViewer
si inserisce all'interno di ignora l'evento.
Se si effettua la ListBox
più alto e più stretto del esterna ScrollViewer
, e dargli elementi sufficienti in modo che la stessa può ListBox
scorrere le voci, vedrete 2 barre di scorrimento verticale: 1 nel ListBox
, e 1 al di fuori del ListBox
per il tuo esterno ScrollViewer
. Quando il cursore del mouse si trova all'interno dello ListBox
, lo ListBox
scorrerà gli elementi con il suo interno ScrollViewer
e il suo Border
rimarrà al suo posto. Quando il cursore del mouse si trova all'esterno dello ScrollViewer
all'interno dello ScrollViewer
esterno, lo - lo si può verificare notando che la posizione ListBox
Border
cambia.
Se si desidera un esterno ScrollViewer
per scorrere l'intero ListBox
di controllo (compresi i Border
e non solo le voci), è necessario ri-stile ListBox
in modo che esso non ha un interno ScrollViewer
, ma si' Dovrai anche assicurarti che diventi automaticamente più grande in base ai suoi articoli.
Non consiglio questo approccio per un paio di motivi.Potrebbe avere senso se ci sono altri controlli all'interno del ScrollViewer
insieme allo ListBox
, ma il campione non lo indica. Inoltre, se hai un sacco di articoli nello ListBox
, creerai ListBoxItem
s per ogni singolo, eliminando ogni vantaggio che il valore predefinito, non reindirizzato ListBox
ti dà a causa del valore predefinito VirtualizingStackPanel
.
Fateci sapere quali sono i vostri requisiti effettivi.
Edit: Ok, ora ho un po 'meglio un'idea, con l'aggiunta di quelle immagini. L'effetto che si ottiene è che quando ci sono abbastanza elementi da far scorrere e viene visualizzata la barra di scorrimento, l'area disponibile deve ridursi un po 'orizzontalmente perché il modello di ScrollViewer
utilizza uno Grid
. Queste sembrano essere le opzioni, in ordine di meno a-meglio:
- Re-stile
ListBox
di non avere un ScrollViewer
e utilizzare il vostro re-styled ScrollViewer
al di fuori del ListBox
. Dovresti quindi forzare lo ListBox
ad essere abbastanza alto da mostrare ogni elemento dello stesso Style
e ora hai perso la virtualizzazione dell'interfaccia utente. Se hai intenzione di mostrare centinaia di elementi nell'elenco, non devi assolutamente perdere .
- Ridisegnare
ListBox
e impostare ControlTemplate
per utilizzare uno ScrollViewer
con lo stile già creato per esso che posiziona la barra di scorrimento sul contenuto anziché in una colonna separata. Questo è ok (ListBox
arriva a limitare la sua altezza e utilizzare un VirtualizingStackPanel
, yay), ma come hai detto, è necessario prendere coscienza di ciò nel tuo DataTemplate
.
- Ridisegnare lo
ScrollViewer
per lasciare spazio per la barra di scorrimento verticale anche quando non è visibile. Ecco cosa questa opzione appare come:
Per impostazione predefinita, ScrollViewer
utilizza 2 colonne in una Grid
equivalente a questo:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
Così il Width
della colonna della barra di scorrimento è 0 quando la barra di scorrimento non è visibile in quanto Width="Auto"
. Per lasciare spazio per la barra di scorrimento, anche quando è nascosto, leghiamo il Width
di quella colonna alla Width
della barra di scorrimento verticale:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition
Width="{Binding ElementName=PART_VerticalScrollBar, Path=Width}" />
</Grid.ColumnDefinitions>
Così ora la ControlTemplate
nel costume Style
per ScrollViewer
potrebbe essere simile a questo:
<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>
si potrebbe anche fare la colonna contenuti una dimensione fissa e la colonna barra di scorrimento Width="*"
, che potrebbe funzionare meglio nel lungo periodo se l'immagine non è allungata. Ora lo DataTemplate
non deve compensare la larghezza di una barra di scorrimento, poiché ottiene un'area coerente da utilizzare se la barra di scorrimento è visibile o meno.
Probabilmente vorrai controllare il resto dello example ControlTemplate
for ScrollViewer
, ma quegli esempi non sono gli stili predefiniti. Nota che l'esempio mette la barra di scorrimento verticale a sinistra! Si noti anche il commento in fondo a ContentScrollPresenter
.
Aggiornato il mio post .. –