2009-08-18 13 views
5

La rotellina del mouse non funziona quando si inserisce ListBox in un ScrollViewer.Inserimento di ListBox in ScrollViewer: la rotellina del mouse non funziona

Il ListBox in qualche modo "ruba" questo 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> 

Edit: come richiesto da Joel, ha aggiunto il motivo per cui ho fatto questo .. ho fatto perché non mi piace quello che s' il ListBox interna ScrollViewer fa con il mio layout. Ho un'immagine di sfondo, e per di più un ListBox come illustrato di seguito:

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

Ora, quando viene visualizzata la barra di scorrimento, accade quanto segue:

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

Ho creato un Style for a ScrollViewer che mostra la barra di scorrimento in alto del contenuto dell'articolo ListBox. Nel datatemplate dell'articolo ListBox ho riservato un po 'di spazio per la barra di scorrimento.

Grazie, Robbert Dam

risposta

15

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

  1. 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 .
  2. 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.
  3. 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.

+0

Aggiornato il mio post .. –

3

Mi stavo occupando dello stesso problema. Ho impostato il ListBox.ItemsPanel proprietà, senza alcuna 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> 

Spero che questo aiuti.

0

Vedi questo link per un'altra risposta: Scroll in ScrollViewer when mouse over ListBox

Ciao, penso che si può gestire l'evento PreviewMouseWheel di tutto il ListBox. Ciò influirà anche sui singoli articoli purché non gestisca ogni articolo

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