What is the easy way to set spacing between items in StackPanel?
I use a transparent separator, which works well:
<Separator Opacity="0" Height="20"/>
You can of course use margins but then if you want to change the margins you have to update all of the elements.
The separator can even be styled in a static resource.
An attached property could do it too but I think it's overkill.
if all the controls are the same then do as IanR suggested and implement a Style that catches that control. if it's not then you can't create a default style to a base class because it just won't work.
the best way for situations like these is to use a very neat trick - attached properties (aka Behaviors in WPF4)
you can create a class that has an attached property, like so:
public class MarginSetter{ public static Thickness GetMargin(DependencyObject obj) { return (Thickness)obj.GetValue(MarginProperty); } public static void SetMargin(DependencyObject obj, Thickness value) { obj.SetValue(MarginProperty, value); } // Using a DependencyProperty as the backing store for Margin. This enables animation, styling, binding, etc... public static readonly DependencyProperty MarginProperty = DependencyProperty.RegisterAttached("Margin", typeof(Thickness), typeof(MarginSetter), new UIPropertyMetadata(new Thickness(), CreateThicknesForChildren)); public static void CreateThicknesForChildren(object sender, DependencyPropertyChangedEventArgs e) { var panel = sender as Panel; if (panel == null) return; foreach (var child in panel.Children) { var fe = child as FrameworkElement; if (fe == null) continue; fe.Margin = MarginSetter.GetMargin(panel); } }}
now, to use it, all you need to do is to attach this attached property to any panel you want, like so:
<StackPanel local:MarginSetter.Margin="10"> <Button Content="hello " /> <Button Content="hello " /> <Button Content="hello " /> <Button Content="hello " /></StackPanel>
Completely reusable of course.
The accepted answer doesn't work anymore. But I used that answer and the blog the author of that answer (Elad Katz) to make a working code (tested in .Net Core) that I reproduce here:
public static class EstablecedorMargen { public static Thickness GetMargen(DependencyObject objeto) => objeto != null ? (Thickness)objeto.GetValue(PropiedadMargen) : new Thickness(); public static void SetMargen(DependencyObject objeto, Thickness value) => objeto?.SetValue(PropiedadMargen, value); public static readonly DependencyProperty PropiedadMargen = DependencyProperty.RegisterAttached("Margen", typeof(Thickness), typeof(EstablecedorMargen), new UIPropertyMetadata(new Thickness(), CambiĆ³)); public static void CambiĆ³(object sender, DependencyPropertyChangedEventArgs e) { if (!(sender is Panel panel)) return; panel.Loaded += new RoutedEventHandler(EstablecerMargenControlesHijos); } public static void EstablecerMargenControlesHijos(object sender, RoutedEventArgs e) { if (!(sender is Panel panel)) return; foreach (var hijo in panel.Children) { if (!(hijo is FrameworkElement feHijo)) continue; feHijo.Margin = GetMargen(panel); } } }
Then you use:
<StackPanel local:EstablecedorMargen.Margen="10" > <Button Content="1" /> <Button Content="2" /> <Button Content="3" /> </StackPanel>