135

I followed this small "tutorial" on how to add a scrollbar to an ItemsControl, and it works in Designer view, but not when I compile and execute the program (only the first few items show up, and no scrollbar to view more - even when VerticalScrollbarVisibility is set to "Visible" instead of "Auto").

Any idea on how to solve this?


This is the code I use to show my items (normally I work with Databinding, but to see the items in my Designer I added them manually):

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

And this is my Template:

<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
  • 2,080
  • 3
  • 18
  • 30

3 Answers3

277

To get a scrollbar for an ItemsControl, you can host it in a ScrollViewer like this:

<ScrollViewer VerticalScrollBarVisibility="Auto">
  <ItemsControl>
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
    <uc:UcSpeler />
  </ItemsControl>
</ScrollViewer>
Drew Noakes
  • 266,361
  • 143
  • 616
  • 705
Oskar
  • 7,215
  • 4
  • 32
  • 42
  • 17
    It's so obvious when you see it... As I'm coming from Windows Forms, I often find myself stuck in the wrong mindset. It seems that WPF rights a lot of wrongs... +1. – Christoffer Lette Nov 09 '10 at 08:26
  • 3
    Thanks -very helpful. I agree with Lette that my WinForms brain doesn't "get" this initially. – itsmatt Dec 14 '10 at 20:22
  • 2
    I just tried this right here and it still did not work. The ItemsControl flows right off its parent container and no ScrollBar is visible at all. – Ristogod Jun 21 '11 at 16:36
  • 10
    @Ristogod If you host the ScrollViewer inside something that lets its content grow as much as needed, for example a StackPanel, scrolling will not work. What's the parent container? Try setting a fixed height on either the ScrollViewer or the parent, does that help? – Oskar Jun 22 '11 at 06:56
  • I've got a question for you Oskar (or anyone else). I had the ItemsControl within a StackPanel, and like you said, it didn't allow the scrollbars if the ScrollViewer to appear. So I got rid of the stack panel and put a fixed maximum height to the scroll viewer. OK, that does work, but I don't quite want that, either, because I want the user to be able to resize the window. How do I account for that? – Rod Oct 14 '11 at 15:55
  • 5
    @Rod You can host the ScrollViewer in a DockPanel or a Grid instead of a StackPanel to achieve this. – Oskar Oct 16 '11 at 14:38
  • 1
    I'm late to the party here, but doesn't this disable virtualization? Not saying that everything needs virtualization - just trying to find a solution that doesn't disable virtualization. – Brandon Mar 07 '18 at 23:48
  • 1
    This answer explains how to achieve scrolling without sacrificing item virtualization, which can improve performance when you have many items: https://stackoverflow.com/a/2784220/24874 – Drew Noakes Jun 20 '20 at 11:27
88

You have to modify the control template instead of ItemsPanelTemplate:

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

Maybe, your code does not working because StackPanel has own scrolling functionality. Try to use StackPanel.CanVerticallyScroll property.

Andriy Shvydky
  • 2,136
  • 1
  • 13
  • 18
  • 1
    The StackPanel CanVerticallyScroll property didn't work, I'm afraid. – Xuntar Jan 08 '10 at 16:29
  • StackPanel CanVerticallyScroll didnt work but the code example given here worked for me. Thanks – Souvik Basu May 31 '11 at 18:43
  • This works. I am looking for making scrollviewer inside instead of outside, because https://github.com/punker76/gong-wpf-dragdrop requires it. – HelloSam Jul 25 '13 at 05:32
3

Put your ScrollViewer in a DockPanel and set the DockPanel MaxHeight property

[...]
<DockPanel MaxHeight="700">
  <ScrollViewer VerticalScrollBarVisibility="Auto">
   <ItemsControl ItemSource ="{Binding ...}">
     [...]
   </ItemsControl>
  </ScrollViewer>
</DockPanel>
[...]
Lou
  • 235
  • 4
  • 11