Reputation: 1781
I have the following XAML in my window:
<WrapPanel>
<WrapPanel.Resources>
<Style TargetType="Rectangle">
<Setter Property="Margin" Value="10,10,10,10"/>
<Setter Property="VerticalAlignment" Value="Top"/>
</Style>
</WrapPanel.Resources>
<Rectangle Height="100" Width="100" Fill="Red"/>
<Rectangle Height="200" Width="200" Fill="Yellow"/>
<Rectangle Height="150" Width="150" Fill="Green"/>
<Rectangle Height="50" Width="50" Fill="Blue"/>
<Rectangle Height="250" Width="250" Fill="Purple"/>
</WrapPanel>
Which produces the following UI in the designer:
What I'm looking for is a way to 'horizontally align' the child elements in the wrap panel, so that the window would look something like this:
Is there any way to achieve this in a wrap panel or do I need to consider using other controls or writing a custom control?
This image additionally illustrates what I'm trying to achieve:
Upvotes: 4
Views: 1984
Reputation: 4136
Using a few different techniques, you may be able to get to where you want to be. This SO answer shows how to define responsive column widths:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
If that isn't enough, you could go down the path of having a custom control that uses a grid layout and repositions which column/row each child control is currently in, and on a control or window resize event, redo the layout positioning of what is where based upon columns / pixel calculations.
UPDATE:
For a custom control, you could try something similar to this:
public class CustomLayout : Control { private List children;
public CustomLayout()
{
children = new List<Control>();
}
public void AddChild(Control childToAdd)
{
children.Add(childToAdd);
// TODO: Determine if new layout is needed.
}
public void RemoveChild(Control childToRemove)
{
children.Remove(childToRemove);
// TODO: Determine if new layout is needed.
}
// Call to update the layout.
private void PerformLayout(int columns, int rows)
{
Grid layoutGrid = new Grid();
// TODO: Programmatically build grid layout.
RowDefinition row = new RowDefinition();
row.Height = 100;
layoutGrid.Rows.Add(row);
// Methods for layout:
// Grid.SetRow(rowID, childControl);
// Grid.SetColumn(columnID, childControl);
// Note: This may produce some flashing on resize, so there may be better ways to remove/add the grid such as redoing rows and columns instead.
Controls.Clear();
Controls.Add(layoutGrid);
}
// Should be called when the window or parent resizes. I can't remember the events in question.
public void OnResize()
{
int columns;
int rows;
// TODO: Calculate columns/rows
PerformLayout(columns, rows);
}
}
Hopefully this gets you going in the right direction. Please keep in mind that this is pseudo code and may not fully compile.
Upvotes: 1
Reputation: 10744
It looks like what you want is a Grid with rows and columns.
<Grid>
<Grid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Margin" Value="10,10,10,10"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle Height="100" Width="100" Fill="Red" Grid.Column="0"/>
<Rectangle Height="200" Width="200" Fill="Yellow" Grid.Column="1"/>
<Rectangle Height="150" Width="150" Fill="Green" Grid.Column="2"/>
<Rectangle Height="50" Width="50" Fill="Blue" Grid.Column="3"/>
<Rectangle Height="250" Width="250" Fill="Purple" Grid.Row="1"/>
</Grid>
This achieves the exact layout of your second picture, but doesn't wrap items as window size changes. To do that you would probably need a custom Grid control that dynamically arranges children as container is resized.
Upvotes: 1