WPF: ItemsControl with scrollbar (ScrollViewer)

130

Postępowałem zgodnie z tym małym "samouczkiem", jak dodać pasek przewijania do ItemsControl i działa on w widoku projektanta, ale nie wtedy, gdy kompiluję i uruchamiam program (pojawia się tylko kilka pierwszych elementów i brak paska przewijania, aby wyświetlić więcej - nawet gdy VerticalScrollbarVisibility jest ustawiona na „Visible” zamiast „Auto”).

Masz jakiś pomysł, jak to rozwiązać?


To jest kod, którego używam do wyświetlania moich elementów (zwykle pracuję z Databinding, ale aby zobaczyć elementy w moim Projektancie, dodałem je ręcznie):

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

A to jest mój szablon:

<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
źródło

Odpowiedzi:

267

Aby uzyskać pasek przewijania dla ItemsControl, możesz umieścić go w ScrollViewertakim miejscu:

<ScrollViewer VerticalScrollBarVisibility="Auto">
  <ItemsControl>
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
  </ItemsControl>
</ScrollViewer>
Oskar
źródło
17
To takie oczywiste, kiedy to widzisz ... Ponieważ wychodzę z Windows Forms, często utknąłem w złym sposobie myślenia. Wygląda na to, że WPF naprawia wiele krzywd ... +1.
Christoffer Lette
3
Dzięki - bardzo pomocne. Zgadzam się z Lette, że mój mózg WinForms początkowo tego nie „rozumie”.
itsmatt
2
Właśnie spróbowałem tego tutaj i nadal nie działa. ItemsControl przepływa bezpośrednio ze swojego kontenera nadrzędnego i żaden pasek ScrollBar nie jest w ogóle widoczny.
Ristogod
9
@Ristogod Jeśli umieścisz ScrollViewer w czymś, co pozwala jego zawartości rosnąć tak bardzo, jak potrzeba, na przykład StackPanel, przewijanie nie będzie działać. Co to jest kontener nadrzędny? Spróbuj ustawić stałą wysokość w ScrollViewer lub nadrzędnym, czy to pomoże?
Oskar
4
@Rod Aby to osiągnąć, możesz hostować ScrollViewer w DockPanel lub Grid zamiast w StackPanel.
Oskar
86

Musisz zmodyfikować szablon kontrolny zamiast ItemsPanelTemplate:

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

Być może Twój kod nie działa, ponieważ StackPanel ma własną funkcję przewijania. Spróbuj użyć właściwości StackPanel.CanVerticallyScroll .

Andriy Shvydky
źródło
1
Obawiam się, że właściwość StackPanel CanVerticallyScroll nie działa.
Xuntar
StackPanel CanVerticallyScroll nie działał, ale podany tutaj przykład kodu zadziałał dla mnie. Dzięki
Souvik Basu
To działa. Szukam zrobienia scrollviewera wewnątrz zamiast na zewnątrz, ponieważ github.com/punker76/gong-wpf-dragdrop tego wymaga.
HelloSam,
3

Umieść ScrollViewer w DockPanel i ustaw właściwość DockPanel MaxHeight

[...]
<DockPanel MaxHeight="700">
  <ScrollViewer VerticalScrollBarVisibility="Auto">
   <ItemsControl ItemSource ="{Binding ...}">
     [...]
   </ItemsControl>
  </ScrollViewer>
</DockPanel>
[...]
Lou
źródło