wpfscrollviewer

ScrollViewer stopped working after some changes in layout


do you know why my scrollviewer isn't working? (WPF)

<Grid Grid.Row="1" Grid.Column="1" Width="350">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="1" Margin="10,0,0,0">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0">
                <Run Text="{Binding SelectedItem.Name}" FontFamily="/Fonts/#Cascadia Mono" FontWeight="SemiBold" FontSize="18"/>
                <Run Text="  "/>
                <Run Text="{Binding SelectedItem.Version}" Foreground="Gray" FontFamily="Open Sans" FontSize="16"/>
            </TextBlock>
            <Button x:Name="installButton" Grid.Column="1" Content="{Binding InstallButtonHeader}" 
                Visibility="Collapsed" Margin="10,-5,0,-10" Command="{Binding InstallCommand}"/>
        </Grid>
        <TextBlock Text="{Binding SelectedItem.Author}" FontSize="12" Foreground="Gray" FontFamily="Open Sans"/>
    </StackPanel>
    <ScrollViewer Grid.Row="2" Margin="10" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
        <TextBlock Text="{Binding SelectedItem.LongDescription}" TextWrapping="Wrap"/>
    </ScrollViewer>
</Grid>

It worked here without problems:

<Grid Grid.Row="1" Grid.Column="1" Width="350">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <StackPanel Grid.Row="1" Margin="10,0,0,0">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding SelectedItem.Name}" FontFamily="/Fonts/#Cascadia Mono" FontWeight="SemiBold" FontSize="18"/>
            <TextBlock Text="  "/>
            <TextBlock Text="{Binding SelectedItem.Version}" Foreground="Gray" FontFamily="Open Sans" FontSize="16" VerticalAlignment="Center"/>
        </StackPanel>
        <TextBlock Text="{Binding SelectedItem.Author}" FontSize="12" Foreground="Gray" FontFamily="Open Sans"/>
    </StackPanel>
    <Button x:Name="installButton" Grid.Row="2" Content="{Binding InstallButtonHeader}" Visibility="Collapsed" Margin="10,10,0,0" Command="{Binding InstallCommand}"/>
    <ScrollViewer Grid.Row="3" Margin="10" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
        <TextBlock Text="{Binding SelectedItem.LongDescription}" TextWrapping="Wrap"/>
    </ScrollViewer>
</Grid>

Not working one had auto height enabled, I thought that this was the problem, but after removing it, error was still occuring.


Solution

  • In case of the ScrollViewer it always needs a size constraint.

    Using a row height of * means the element inside the row can take the remaining available size. This is results in a concrete height value (what ever the remaining height of the available height may be).
    A height of Auto means the element inside the row can have any size it desires - even if it means it would exceed the available space (stretch to infinity).

    Now UI elements have different sizing behaviors. Some like the StackPanel strive to occupy the least possible space while a control like the ScrollViewer will always take as much space as possible (it's greedy). This means, if the ScrollViewer is inside a container that doesn't put a size constraint on it (for example by setting the row height of a parent Grid to Auto) it will stretch to occupy an infinite size.

    Because everything will fit into an infinite area, the child elements of the ScrollViewer will now always fit. Now that everything always fits the available area, the scrollable area becomes 0: because the scroll bar's purpose is to allow to bring elements that doesn't fit the available space into view. If everything fits than there is nothing to scroll into view.

    To solve this problem the ScrollViewer must have a size constraint. Either implicitly imposed by the parent container e.g., by setting row height of a Grid to a value other than Auto, or by given the ScrollViewer an explicit Height and Width.