Auto Margin between Panel elements
Auto Margin between Panel elements
How do you achieve a simple alignment of multiple elements within a panel in WPF?
If you’re doing masks with multiple Textblocks and Textboxes you might have asked yourself exactly this question. In Winforms this wasn’t a trivial problem because you had to set the margin or padding of each element yourself. Fortunately this is a lot easier in WPF now…
Without doing further adjustments you have to set the margin for each element within the panel just like it was in Winforms before. This is kinda irritating because if you want to change the distance between the elements you have to change it for every single element by hand.
<Grid> //... <TextBlock Text="ArtNr:" Grid.Row="0" Grid.Column="0" /> <TextBox Margin="0,0,0,3" Grid.Row="0" Grid.Column="1" /> <TextBlock Text="EAN:" Grid.Row="0" Grid.Column="2" /> <TextBox Margin="0,0,0,3" Grid.Row="0" Grid.Column="3" /> //.. </Grid>
There is a solution called “Attached Behavior”
The keyword to the solution is Attached Behavior“. You simply have to create a Behaviorclass that adjusts the margin for each childelement within a panel on load. In my solution I added / subtracted the margin value because this way you also have the possibility to create an individual distance within the panel, too.
<Grid>
<i:Interaction.Behaviors>
<behaviors:MarginBetweenChildsBehavior Margin="0,0,0,3" />
</i:Interaction.Behaviors>
//...
<TextBlock Text="ArtNr:" Grid.Row="0" Grid.Column="0" />
<TextBox Grid.Row="0" Grid.Column="1" />
<TextBlock Text="EAN:" Grid.Row="0" Grid.Column="2" />
<TextBox Grid.Row="0" Grid.Column="3" />
//..
</Grid>
What is i:Interaction?
It is a markup extension from the “System.Windows.Interactivity.dll” that was shipped with Expression Blend. It is also possible to receive it via NuGet.
The Result:
Each element was added a margin of “0,0,0,3”. Now it looks like this:

The code for my Class : MarginBetweenChildsBehavior
public class MarginBetweenChildsBehavior : Behavior<Panel>
{
public static readonly DependencyProperty MarginProperty =
DependencyProperty.Register("Margin", typeof (Thickness), typeof (MarginBetweenChildsBehavior),
new UIPropertyMetadata(new Thickness(), MarginChangedCallback));
public Thickness Margin
{
get { return (Thickness) GetValue(MarginProperty); }
set { SetValue(MarginProperty, value); }
}
private static void MarginChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Make sure this is put on a panel
var panel = d as Panel;
if (panel == null) return;
}
protected override void OnAttached()
{
AssociatedObject.Loaded += OnPanelLoaded;
}
protected override void OnDetaching()
{
AssociatedObject.Loaded -= OnPanelLoaded;
}
private void OnPanelLoaded(object sender, RoutedEventArgs e)
{
var panel = sender as Panel;
// Go over the children and set margin for them:
foreach (object child in panel.Children)
{
var fe = child as FrameworkElement;
if (fe == null) continue;
fe.Margin = new Thickness(fe.Margin.Left + Margin.Left, fe.Margin.Top + Margin.Top,
fe.Margin.Right + Margin.Right, fe.Margin.Bottom + Margin.Bottom);
}
}
}
