Reputation: 10234
I have the following layout in my window:
Grid
with two columnsGridSplitter
which resizes grid columnsStackPanel
StackPanel
is oriented vertically and has 2 children: TextBlock
and a WrapPanel
WrapPanel
has two Grid
s as childrenGrid
child contains one Image
Grid
contains a StackPanel with 3 TextBlock
s oriented vertically. The XAML code looks like this:
<Window>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
<StackPanel Grid.Column="1" Margin="5,0,0,0" Orientation="Vertical"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="Now here's a silly poem for you." />
<WrapPanel>
<Grid Name="GridForImage">
<Image Width="200" Height="200" Source="Image.jpg" />
</Grid>
<Grid Name="GridForText">
<StackPanel Orientation="Vertical">
<TextBlock TextWrapping="WrapWithOverflow" Text="Roses are red." />
<TextBlock TextWrapping="WrapWithOverflow" Text="Violets are blue." />
<TextBlock TextWrapping="WrapWithOverflow" Text="You belong in a zoo." />
</StackPanel>
</Grid>
</WrapPanel>
</StackPanel>
</Grid>
</Window>
Once the window opens, the second column is wide enough to allow grids GridForImage
and GirdForText
to be placed next to each other horizontally. If I shrink the width of the second column using the grid splitter, the GridForText
grid gets placed underneath the GridForImage
at one point, which is quite expected.
Here's what I would like to achieve:
GridForText
to shrink its width to a certain size and to remain positioned to the right of the GridForImage
, as I move the grid splitter to the right side of the window. Then, when the width shrinks to a certain value, say 200px, it should get placed underneath the GridForImage
, i.e. WrapPanel
should do its magic. Right now, the GridForText
doesn't resize at all, it just gets placed underneath when it's current width becomes too large for the width of the WrapPanel
. GridForText
does get placed underneath the GridForImage
, I want GridForImage
to fill the entire width of the WrapPanel
's width. Is all this possible and what should I do? Thank you all.
Upvotes: 0
Views: 3459
Reputation: 24453
You're essentially trying to use two distinct layout modes so you just need to set up the two distinct states in your layout and then add bindings or triggers to switch between them at the point when you want to switch modes (i.e. width = 200). Using a Grid is the most flexible and gives you a lot more control over the relative sizes but requires more settings and would work best in a ControlTemplate or DataTemplate where you can use Triggers to set a bunch of things at once based on a condition.
Here's a more compact example using UniformGrid with some Bindings and a converter. I removed the fixed sizing on the Image - try Stretch="Fill" if you care more about filling width than aspect ratio. I also changed one StackPanel to a DockPanel to maintain vertical stretching for its children and added a Background to one of the TextBlocks just to show how much Width it's really getting:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
<DockPanel Grid.Column="1" Margin="5,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="Now here's a silly poem for you." DockPanel.Dock="Top"/>
<UniformGrid Rows="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={x:Static local:LayoutModeConverter.Row}, ConverterParameter=200}"
Columns="{Binding RelativeSource={RelativeSource Self}, Path=ActualWidth, Converter={x:Static local:LayoutModeConverter.Column}, ConverterParameter=200}">
<Image Source="Image.jpg" />
<StackPanel Orientation="Vertical">
<TextBlock TextWrapping="WrapWithOverflow" Text="Roses are red." Background="Red" />
<TextBlock TextWrapping="WrapWithOverflow" Text="Violets are blue." />
<TextBlock TextWrapping="WrapWithOverflow" Text="You belong in a zoo." />
</StackPanel>
</UniformGrid>
</DockPanel>
</Grid>
And the converter:
public class LayoutModeConverter : IValueConverter
{
public static readonly LayoutModeConverter Row = new LayoutModeConverter { RowMode = true };
public static readonly LayoutModeConverter Column = new LayoutModeConverter { RowMode = false };
public bool RowMode { get; set; }
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double width = System.Convert.ToDouble(value);
double targetWidth = System.Convert.ToDouble(parameter);
if (RowMode)
return width > targetWidth ? 1 : 2;
else
return width > targetWidth ? 2 : 1;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Upvotes: 1