How to force Grid to shrink an auto sized row that contains ScrollViewer (when needed)?
Inspired by Eirik's approach of constraining a greedy container by putting it inside other tight container, I've discovered a really simple way to achieve what I wanted. I only needed a container that shrinks its one child first, then (when the first one completely disappears) the second one. And there is such container: the DockPanel. Here goes:
<DockPanel LastChildFill="False">
<DockPanel DockPanel.Dock="Top">
<TextBlock DockPanel.Dock="Bottom" TextWrapping="Wrap" Grid.Row="1">Automatically wrapped text of unknown length.</TextBlock>
<ScrollViewer>
<TextBlock TextWrapping="Wrap">In this case the element is too big to fit inside whole space (the black box) with the blue text below. I want the scrollbar to be shown instead of moving the blue text outside of the black box (and clipped)</TextBlock>
</ScrollViewer>
</DockPanel>
</DockPanel>
As simple as that! :) I hope it helps someone.
<Grid Name="outerGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Canvas>
<Grid MaxWidth="{Binding ElementName=outerGrid, Path=ActualWidth}" MaxHeight="{Binding ElementName=outerGrid, Path=ActualHeight}">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer Width="{Binding ElementName=outerGrid, Path=ActualWidth}">
<TextBlock TextWrapping="Wrap">In this case the element is too big to fit inside whole space (the black box) with the blue text below. I want the scrollbar to be shown instead of moving the blue text outside of the black box (and clipped)</TextBlock>
</ScrollViewer>
<TextBlock TextWrapping="Wrap" Grid.Row="1">Automatically wrapped text of unknown length.</TextBlock>
</Grid>
</Canvas>
</Grid>
The auto height will grow to match the height of the content of that row.
The star height will let that row grow in height to fill the rest of the height of the grid, preventing the ScrollViewer
to grow more than what's visible.
Edit: If you put the Grid inside another Grid like the XAML above you should get the behavior you want. The second row of the outer row acts as a "filler" to fill the rest of the space the outer Grid.
Edit 2: Try the edited XAML above. I've put the inner Grid
inside a Canvas
(to prevent clipping) and bound the MaxWidth
and MaxHeight
of the inner Grid
to the ActualWidth
and ActualHeight
of the outer Grid
to keep the inner Grid
the same size as the outer Grid
.
Edit 3: Added binding to the Width
of the ScrollViewer
to keep it the same width as the rest.