40

I am using a scrollviewer control around my stack panel which contains an ItemsControl. When there are many items in the ItemsControl it is suppose to scroll but for some reason it just cuts of the items. Here is the code:

<StackPanel>
    <ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Visible">
        <ItemsControl  Name="icEvents" Width="Auto" Height="100"  Background="AliceBlue" 
                       ItemsSource="{Binding Path=EventSources}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="Source:"/>
                        <TextBlock Text="{Binding Path=Source}" />
                        <TextBlock Text="Original Source:"/>
                        <TextBlock Text="{Binding Path=OriginalSource}" />
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>
</StackPanel>
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
azamsharp
  • 19,710
  • 36
  • 144
  • 222

5 Answers5

56

Try a grid around your ScrollViwer instead of the StackPanel. I think StackPanel will provide as much height as the internal content wants, so here the Scrollviwer doesn't work properly since its height is not get restricted by its parent control.

You can understand the issue from the example below.

<StackPanel>
    <ScrollViewer>
        <ItemsControl >
            <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
        </ItemsControl>
    </ScrollViewer>
</StackPanel>

Above code is similar to yours and it doesn't give you scrollbars. But see the below code in which I changed only the StackPanel to a Grid(Any panel which respects the size of its children based on panels size but stackpanel doesn't)

<Grid>
    <ScrollViewer>
        <ItemsControl >
            <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
            <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
            <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
        </ItemsControl>
    </ScrollViewer>
</Grid>

UPDATE : But if you really need to use StackPanel then you might need to set the size for your ScrollViwer to get the Content scroll

akjoshi
  • 15,374
  • 13
  • 103
  • 121
Jobi Joy
  • 49,102
  • 20
  • 108
  • 119
  • This might not be possible since everything is inside the StackPanel. There is NO grid on the page. Only master stackpanel which contains two other stackpanels. This even happens when I say height of stackpanel to be like 100. – azamsharp Jul 15 '09 at 18:19
  • The problem is that every control on the Window is contained in a master stack panel control. – azamsharp Jul 15 '09 at 18:21
  • 2
    But if you really need to use StackPanel then you might need to set the size for your ScrollViwer to get the Content scroll, because as I said earlier a StackPanel doesnt respect its children's height or width. So we have to set a height and width when we use StackPanel – Jobi Joy Jul 15 '09 at 18:29
  • 1
    I set the height on the ScrollViewer and it worked! Thanks a lot! – azamsharp Jul 15 '09 at 18:38
  • 1
    Check my answer: it solves the problem binding to the actualHeight of the StackPanel – Eduardo Molteni Jul 15 '09 at 18:51
  • Thanks the `Grid` solved my problem. With a `StackPanel` I found the `ScrollViewer` behaved oddly and know I understand the reason why. – Shaun Wilde Sep 23 '12 at 21:28
30

You must fix the Height of the Scrollviewer, but can easily bind to the StackPanel ActualHeight:
(tested code)

<StackPanel Name="mypanel">
   <ScrollViewer Height="{Binding ElementName=mypanel, Path=ActualHeight}">
       <ItemsControl>
          <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" />
      </ItemsControl>
   </ScrollViewer>
</StackPanel>

Or better yet, if you can't change the name of the StackPanel:

<StackPanel>
    <ScrollViewer Height="{Binding RelativeSource={RelativeSource FindAncestor, 
                        AncestorType={x:Type StackPanel}}, Path=ActualHeight}">
       <ItemsControl>
          <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" Width="200"/>
          <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" />
          <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" />
      </ItemsControl>
   </ScrollViewer>
</StackPanel>

It is a "You first" problem, the StackPanel ask the ScrollViewer for the Height and the ScrollViewer ask the StackPanel for the max Height it can be.

Eduardo Molteni
  • 38,786
  • 23
  • 141
  • 206
5

The ItemsControl should contain the ScrollViewer, not the other way around. All that the ScrollViewer knows about is the ItemsControl itself in your case - it doesn't know about the inner items.

Try something like this:

<ItemsControl Name="icEvents" Width="Auto" Height="100"
    Background="AliceBlue"
    ItemsSource="{Binding Path=EventSources}">
    <ItemsControl.ItemTemplate>
        <DataTemplate> 
            <StackPanel>
                <TextBlock Text="Source:"/>
                <TextBlock Text="{Binding Path=Source}" />
                <TextBlock Text="Original Source:"/>
                <TextBlock Text="{Binding Path=OriginalSource}" />
            </StackPanel>  
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.Template>
        <ControlTemplate TargetType="ItemsControl">
            <ScrollViewer VerticalScrollBarVisibility="Auto">
                <ItemsPresenter Margin="5" />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
</ItemsControl>
Andy
  • 30,088
  • 6
  • 78
  • 89
  • It is not necessary to have a scrollviwer, the problem in the question is the StackPanel. – Jobi Joy Jul 15 '09 at 18:16
  • 2
    You need a ScrollViewer somewhere, though, since by default ItemsControl doesn't scroll. I've used this code and it works, although your answer would probably work as well. – Andy Jul 15 '09 at 18:18
  • Yeah your code also works only if he removes the outer StackPanel and it doesnt matter you have a scrollbar inside the ControlTemplate or outside of the ItemsControl both are almost same. – Jobi Joy Jul 15 '09 at 18:22
  • This was my problem - I was doing this the wrong way - excellent man thanks – AltF4_ Sep 20 '15 at 12:18
0

I had a problem whereby I showed an ItemsControl in a Grid and in order to see the scrollbars, I had to give this Grid cell *-sized height.

However, this meant that the ItemsControl always filled the cell even when there were only a few values.

I wanted the ItemsControl to be only big enough to show what it had but if it had too many items then I wanted it to scroll. In order words I wanted this to work only any size monitor.

This code in the Loaded event worked for me:

Size x = new Size(double.PositiveInfinity, double.PositiveInfinity);
myItemscontrol.Measure(x);
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
0

The Scroll needs to be the parent of the resizing child so, put the resizing control(in this instance the stack panel) inside it.

<ScrollViewer>
    <StackPanel>
         <Rectangle Stroke="#FFC3C3C3"  Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
         <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
         <Rectangle Stroke="#FFC3C3C3" Height="300" Fill="Black" StrokeThickness="4" Width="200"/>
         <Rectangle Stroke="#FFC3C3C3" Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
         <Rectangle Stroke="#FFC3C3C3"  Width="200" Height="300" Fill="Black" StrokeThickness="4"/>
    </StackPanel>

MikeT
  • 5,398
  • 3
  • 27
  • 43