How would one create this layout?:
The idea is to keep the blue text always just below the green element BUT when there is not enough space, the green element should be placed inside a scrollable container (with vertical scrollbar visible).
I have tried StackPanel and Grid and both failed. The StackPanel does not shrink rows at all. The Grid does the same if the top RowDefinition's height is set to "auto" (the ScrollViewer inside does not show its scrollbar). If it's set to a star, the blue text is moved down to at least half of the space (depends of the bottom row's height setting). The bottom row's height can be either an "auto" or a star with VerticalAlignment of the blue text set to Top BUT the row's height must be kept at least as big as the text's. Of course the whole area (black box) cannot be stretched by its content - it's determined by the size of the window.
How? Please keep the responses to be based on XAML if possible.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With