Reputation: 13278
See this container where I have two elements. I want them to be evenly spaced, as if I were using justify-content: space-between
(or space-around
) in an HTML flexbox.
<StackPanel Margin="10" Orientation="Horizontal">
<ComboBox DockPanel.Dock="Left" SelectedIndex="0" Padding="6">
<ComboBoxItem Content="Info"/>
</ComboBox>
<Ellipse DockPanel.Dock="Right" Width="20" Height="20" Fill="Red"/>
</StackPanel>
For this particular case, where I want them at either edge of the container, I've managed a workaround using a DockPanel
.
<DockPanel Margin="10" LastChildFill="False">
<ComboBox DockPanel.Dock="Left" SelectedIndex="0" Padding="6">
<ComboBoxItem Content="Info"/>
</ComboBox>
<Ellipse DockPanel.Dock="Right" Width="20" Height="20" Fill="Red"/>
</DockPanel>
However, this is definitely a workaround; if I had some dynamic number of elements that I wanted evenly spaced, it wouldn't work.
Off the top of my head I imagine I could wrap each element in a StackPanel
or other container that could stretch to share the width of its container. But is there a simpler way to set equal spacing?
Using Margin
or Padding
on the individual elements is unacceptable. Unacceptable!!!!!
Upvotes: 1
Views: 4224
Reputation: 16662
You can do the following:
ItemsControl
ItemsPanel
that'll be UniformGrid
IValueConverter
:XAML:
<UserControl x:Class="ConsoleApp1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ConsoleApp1"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400">
<UserControl.Resources>
<local:ItemsControlToRowsConverter x:Key="ItemsControlToRowsConverter" />
</UserControl.Resources>
<Grid>
<Border BorderBrush="Black" BorderThickness="1">
<ItemsControl x:Name="ItemsControl">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="{Binding ElementName=ItemsControl, Converter={StaticResource ItemsControlToRowsConverter}}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<Border Width="50" Height="50" Background="Red" Margin="2"/>
<Border Width="50" Height="50" Background="Green" Margin="2"/>
<Border Width="50" Height="50" Background="Blue" Margin="2"/>
<Border Width="50" Height="50" Background="Yellow" Margin="2"/>
</ItemsControl>
</Border>
</Grid>
</UserControl>
Converter:
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ConsoleApp1
{
public class ItemsControlToRowsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is ItemsControl itemsControl))
return DependencyProperty.UnsetValue;
return itemsControl.Items.Count;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
Pile things up and adjust the converter to your tastes.
Upvotes: 2