WPF: ItemsControl avec barre de défilement (ScrollViewer)

128

J'ai suivi ce petit "tutoriel" sur la façon d'ajouter une barre de défilement à un ItemsControl, et cela fonctionne en mode Designer, mais pas lorsque je compile et exécute le programme (seuls les premiers éléments apparaissent, et aucune barre de défilement pour en voir plus - même lorsque VerticalScrollbarVisibility est défini sur "Visible" au lieu de "Auto").

Une idée sur la façon de résoudre ce problème?


C'est le code que j'utilise pour afficher mes éléments (normalement je travaille avec Databinding, mais pour voir les éléments dans mon Designer, je les ai ajoutés manuellement):

<ItemsControl x:Name="itemCtrl" Style="{DynamicResource UsersControlStyle}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Top">
            </StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
</ItemsControl>

Et voici mon modèle:

<Style x:Key="UsersControlStyle" TargetType="{x:Type ItemsControl}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ItemsControl}">
                <Border SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                    <ScrollViewer VerticalScrollBarVisibility="Visible">
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Xuntar
la source

Réponses:

261

Pour obtenir une barre de défilement pour un ItemsControl, vous pouvez l'héberger de la manière ScrollViewersuivante:

<ScrollViewer VerticalScrollBarVisibility="Auto">
  <ItemsControl>
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
  </ItemsControl>
</ScrollViewer>
Oskar
la source
16
C'est tellement évident quand vous le voyez ... Comme je viens de Windows Forms, je me retrouve souvent coincé dans le mauvais état d'esprit. Il semble que WPF corrige beaucoup de torts ... +1.
Christoffer Lette
3
Merci - très utile. Je suis d'accord avec Lette que mon cerveau WinForms ne «comprend» pas cela au départ.
itsmatt
1
J'ai juste essayé cela ici et cela ne fonctionnait toujours pas. Le ItemsControl s'écoule directement de son conteneur parent et aucun ScrollBar n'est visible du tout.
Ristogod
8
@Ristogod Si vous hébergez le ScrollViewer dans quelque chose qui permet à son contenu de croître autant que nécessaire, par exemple un StackPanel, le défilement ne fonctionnera pas. Quel est le conteneur parent? Essayez de définir une hauteur fixe sur ScrollViewer ou sur le parent, cela vous aide-t-il?
Oskar
4
@Rod Vous pouvez héberger ScrollViewer dans un DockPanel ou une Grid au lieu d'un StackPanel pour y parvenir.
Oskar
79

Vous devez modifier le modèle de contrôle au lieu de ItemsPanelTemplate:

<ItemsControl >
    <ItemsControl.Template>
        <ControlTemplate>
            <ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>

Peut-être que votre code ne fonctionne pas car StackPanel a sa propre fonctionnalité de défilement. Essayez d'utiliser la propriété StackPanel.CanVerticallyScroll .

Andrey Shvydky
la source
1
La propriété StackPanel CanVerticallyScroll ne fonctionnait pas, j'en ai peur.
Xuntar
StackPanel CanVerticallyScroll n'a pas fonctionné mais l'exemple de code donné ici a fonctionné pour moi. Merci
Souvik Basu
Cela marche. Je cherche à créer un scrollviewer à l'intérieur plutôt qu'à l'extérieur, car github.com/punker76/gong-wpf-dragdrop l' exige.
HelloSam
3

Placez votre ScrollViewer dans un DockPanel et définissez la propriété DockPanel MaxHeight

[...]
<DockPanel MaxHeight="700">
  <ScrollViewer VerticalScrollBarVisibility="Auto">
   <ItemsControl ItemSource ="{Binding ...}">
     [...]
   </ItemsControl>
  </ScrollViewer>
</DockPanel>
[...]
Patatrack
la source