2010-10-18 21 views
2

Je pense que cela devrait être facile, mais j'ai du mal avec ça.Obtenir la référence à ScrollViewer de mon WPF ListBox en C#?

Comment puis-je obtenir une référence au scrollviewer de ma ListBox en C#? J'ai essayé à peu près tout ce que je peux penser. La ListBox est dans un contrôle personnalisé WPF afin que nous utilisions Template.FindName pour obtenir des références à tous nos contrôles. Mon ListBox ressemble à ceci:

<ListBox x:Name="PART_SoundList" 
           ScrollViewer.CanContentScroll="False" 
           ScrollViewer.HorizontalScrollBarVisibility="Auto" 
           ScrollViewer.VerticalScrollBarVisibility="Hidden" Focusable="False" FocusVisualStyle="{x:Null}" 
           HorizontalAlignment="Center" VerticalAlignment="Bottom" BorderThickness="0" 
           ItemContainerStyleSelector="{StaticResource ListBoxItemAlternatingStyleSelector}" 
           ItemsSource="{Binding}" > 

            <ListBox.ItemsPanel> 
             <ItemsPanelTemplate> 
              <WrapPanel Orientation="Vertical" Height="850" Focusable="False" Panel.ZIndex="999" > 
               <WrapPanel.RenderTransform> 
                 <TransformGroup> 
                  <ScaleTransform CenterX="0" CenterY="0" ScaleX=".75" ScaleY=".57" /> 
                 </TransformGroup> 
                </WrapPanel.RenderTransform> 
              </WrapPanel> 
             </ItemsPanelTemplate> 
            </ListBox.ItemsPanel> 

            <ListBox.Template> 
             <ControlTemplate> 
              <ScrollViewer x:Name="Scroller" VerticalAlignment="Bottom" Focusable="False" Style="{StaticResource HorizontalScroller}" > 
               <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Focusable="False" Panel.ZIndex="999" /> 
              </ScrollViewer> 
             </ControlTemplate> 
            </ListBox.Template> 

           </ListBox> 

Template.FindName ("Scroller", cela) que les résultats ScrollViewer à null.

Des idées?

+0

Qu'est-ce que avez-vous besoin d'une référence au ScrollViewer f ou? Seulement curieux parce qu'il pourrait y avoir une approche différente que vous pourriez prendre pour résoudre votre problème. – Ragepotato

Répondre

5

Vous essayez probablement d'obtenir une référence au ScrollViewer trop tôt. Essayez de déplacer votre code dans l'événement chargé et vérifier si elle retourne toujours null:

dans votre constructeur CustomControl/form:

this.Loaded += MainWindow_Loaded; 

void MainWindow_Loaded(object sender, RoutedEventArgs e) 
{ 
    var x = PART_SoundList.Template.FindName("Scroller", PART_SoundList); 
} 
+0

Vous avez raison monsieur. Merci. –

+1

Je ne peux pas trouver '.Findname' après Template! Une idée de ce que je manque? – yalematta

2

Utilisez l'appel récursif à Visual Tree pour récupérer n'importe quel Visual de l'arborescence. Cela vous donne une méthode générique pour obtenir l'élément Visual du type mentionné dans l'arborescence Visual.

+0

J'ai essayé cela (à la fois votre méthode et ma variation de celui-ci plus tôt aujourd'hui) et c'est toujours nul. –

+0

Cette solution provient de la documentation MSDN pour [FrameworkTemplate.FindName, méthode] (http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.findname.aspx). – skst

+0

L'élément enfant doit être capturé dans un spécificateur de type générique.c'est-à-dire, pas

2

Je suppose que le XAML que vous avez ci-dessus fait partie du ControlTemplate pour votre CustomControl, non? Je suppose également que vous obtenez les parties de contrôle sur la méthode OnApplyTemplate(), n'est-ce pas? Si tel est le cas, alors, je pense que ce que vous devez faire est de forcer un appel à PART_SoundList.ApplyTemplate() avant de trouver le ScrollViewer. Ainsi, le code de votre contrôle personnalisé devrait ressembler à ceci:

public class MyControl : Control 
{ 
    private ListBox lb; 
    private ScrollViewer scroller; 

    static MyControl() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl), new FrameworkPropertyMetadata(typeof(MyControl))); 
    } 

    public override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 

     lb = this.Template.FindName("PART_SoundList", this) as ListBox; 
     lb.ApplyTemplate(); 
     scroller = lb.Template.FindName("Scroller", lb) as ScrollViewer; 
    } 
} 
+0

Nice Je n'ai pas maintenant à propos de ApplyTemplate(). La réponse de Claudiu fonctionne pour moi en ce moment mais je suis sûr que je serai capable de l'utiliser sur la route. –

0

Si vous allez utiliser la référence pour faire défiler/vérifier la taille de la fenêtre du devrait être suffisant pour vous.

Vous pouvez y accéder comme dans votre code sous-jacent (Note point de Claudiu d'attente jusqu'à l'événement chargé): Ensuite, faites défiler horizontalement

ListBoxAutomationPeer svAutomation = (ListBoxAutomationPeer)ScrollViewerAutomationPeer.CreatePeerForElement(PART_SoundList); 
// not feeling creative with my var names today... 
IScrollProvider scrollInterface = (IScrollProvider)svAutomation.GetPattern(PatternInterface.Scroll); 

et verticalement chaque fois que vous voulez et à votre contenu de coeurs.

0

Pour ceux qui se ici la recherche d'une réponse à la question initiale:

En C#

ScrollViewer sv = FindVisualChild<ScrollViewer>(MyListBox); 

ou en VB

Dim sv As ScrollViewer = FindVisualChild(Of ScrollViewer)(MyListBox) 

Où en XAML

<ListBox x:Name="MyListBox"> 
</ListBox>