How can I get ScrollViewer to work inside a StackPanel?

In the following WPF XAML the ScrollViewer does not work (it displays a scroll bar but you cannot scroll and the contents go off the window to the bottom).

I can change the outer StackPanel to a Grid and it will work.

However, in my application from which I reproduced the following code, I need to have an outer StackPanel. What do I have to do to the StackPanel to make the ScrollViewer show a usable scrollbar? e.g. VerticalAlignment="Stretch" Height="Auto" don't work.

 <StackPanel>
<ScrollViewer>
<StackPanel>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
</StackPanel>
</ScrollViewer>
</StackPanel>
104301 次浏览

You can't without fixing the height of the StackPanel. It's designed to grow indefinitely in one direction. I'd advise using a different Panel. Why do you "need" to have an outer StackPanel?

This was bugging me for a while too, the trick is to put your stackpanel within a scrollviewer.

Also, you need to ensure that you set the CanContentScroll property of the scroll viewer to True, here's an example:

  <ScrollViewer Grid.Row="1" Margin="299,12,34,54" Name="ScrollViewer1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Height="195" CanContentScroll="True">
<StackPanel Name="StackPanel1" OverridesDefaultStyle="False"  Height="193" Width="376" VerticalAlignment="Top" HorizontalAlignment="Left"></StackPanel>
</ScrollViewer>

Notice that sometimes you might have a StackPanel without realizing it. In my case I had this code

<ScrollViewer>
<ItemsControl ItemsSource="{Binding Pages}"/>
</ScrollViewer>

which worked fine. The "Pages" referenced by the binding was really different, complex UserControls, and I wanted to have only scrollbars on some of them. So I removed the scrollviewer:

 <ItemsControl ItemsSource="{Binding Pages}"/>

And then I put the ScrollViewer as the top element on those of the usercontrols where I wanted them. However, this did not work. The content just flowed off the page. At first i didn't think this question/answer could help me, but the I realized that the default ItemPanel of an ItemsControl is the StackPanel. So I solved my problem by specifying an ItemsPanel that was not the StackPanel:

<ItemsControl ItemsSource="{Binding Pages}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

Indeed, the way I solved that dileman was to remove the outer stack panel and instead set the scrollviewer in the position I wanted inside the main grid.

        <Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="160"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>


<!-- Vertical scrolling grid used in most view states -->


<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto">
<StackPanel Orientation="Horizontal">
<GridView>
...
</GridView>
</StackPanel>
</ScrollViewer>

Moving Grid.Row="1" from StackPanel to ScrollViewer completely solved it for me.

I had a long list of some 40 items to show in a StackPanel, but only the first 20 were showing.

    <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel x:Name="ContentPanel" Margin="12,0,12,0">
<TextBlock Text="{Binding Line1}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<TextBlock Text="" Margin="10,-2,10,0" Style="{StaticResource PhoneTextNormalStyle}" />
...
</StackPanel>
</ScrollViewer>

This is how it works:

<Window x:Class="TabControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabControl"
Title="MainWindow"    Height="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<StackPanel>
<ScrollViewer Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type Border}},Path=ActualHeight}" >
<StackPanel >
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>                <TextBlock Text="This is a test"/>
</StackPanel>
</ScrollViewer>
</StackPanel>

By binding the ScrollViewer's Height to Window's Inner Height.

The logic of re-sizing is we need to give any element fix height or design the view to use render height.

Output:

Scrollbar in Stackpanel

Here's how I would do it if your stack panel is inside a grid:

<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel MaxHeight="{Binding Path=Height,RelativeSource={RelativeSource
AncestorType=Grid}}">
</StackPanel>
</ScrollViewer>
<WrapPanel Orientation="Vertical">
<ScrollViewer>
<WrapPanel Orientation="Vertical">
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
<TextBlock Text="This is a test"/>
</WrapPanel>
</ScrollViewer>
</WrapPanel>