Created
January 17, 2015 12:19
-
-
Save angularsen/90040fb174f71c5ab3ad to your computer and use it in GitHub Desktop.
WPF - Automatic horizontal or vertical spacing in StackPanel and other list like panels
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<StackPanel Orientation="Horizontal" foo:Spacing.Horizontal="5"> | |
<Button>Button 1</Button> | |
<Button>Button 2</Button> | |
</StackPanel> | |
<StackPanel Orientation="Vertical" foo:Spacing.Vertical="5"> | |
<Button>Button 1</Button> | |
<Button>Button 2</Button> | |
</StackPanel> | |
<StackPanel Orientation="Vertical" foo:MarginSetter.Margin="5" foo:MarginSetter.LastItemMargin="5 0"> | |
<Button>Button 1</Button> | |
<Button>Button 2</Button> | |
</StackPanel> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Windows; | |
using System.Windows.Controls; | |
using JetBrains.Annotations; | |
namespace Foo | |
{ | |
public class MarginSetter | |
{ | |
private static Thickness GetLastItemMargin(Panel obj) | |
{ | |
return (Thickness) obj.GetValue(LastItemMarginProperty); | |
} | |
[UsedImplicitly] | |
public static Thickness GetMargin(DependencyObject obj) | |
{ | |
return (Thickness) obj.GetValue(MarginProperty); | |
} | |
private static void MarginChangedCallback(object sender, DependencyPropertyChangedEventArgs e) | |
{ | |
// Make sure this is put on a panel | |
var panel = sender as Panel; | |
if (panel == null) return; | |
// Avoid duplicate registrations | |
panel.Loaded -= OnPanelLoaded; | |
panel.Loaded += OnPanelLoaded; | |
if (panel.IsLoaded) | |
{ | |
OnPanelLoaded(panel, null); | |
} | |
} | |
private static void OnPanelLoaded(object sender, RoutedEventArgs e) | |
{ | |
var panel = (Panel) sender; | |
// Go over the children and set margin for them: | |
for (var i = 0; i < panel.Children.Count; i++) | |
{ | |
UIElement child = panel.Children[i]; | |
var fe = child as FrameworkElement; | |
if (fe == null) continue; | |
bool isLastItem = i == panel.Children.Count - 1; | |
fe.Margin = isLastItem ? GetLastItemMargin(panel) : GetMargin(panel); | |
} | |
} | |
[UsedImplicitly] | |
public static void SetLastItemMargin(DependencyObject obj, Thickness value) | |
{ | |
obj.SetValue(LastItemMarginProperty, value); | |
} | |
[UsedImplicitly] | |
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(), MarginChangedCallback)); | |
public static readonly DependencyProperty LastItemMarginProperty = | |
DependencyProperty.RegisterAttached("LastItemMargin", typeof (Thickness), typeof (MarginSetter), | |
new UIPropertyMetadata(new Thickness(), MarginChangedCallback)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Windows; | |
using JetBrains.Annotations; | |
namespace Foo | |
{ | |
public class Spacing | |
{ | |
public static double GetHorizontal(DependencyObject obj) | |
{ | |
return (double) obj.GetValue(HorizontalProperty); | |
} | |
public static double GetVertical(DependencyObject obj) | |
{ | |
return (double) obj.GetValue(VerticalProperty); | |
} | |
private static void HorizontalChangedCallback(object sender, DependencyPropertyChangedEventArgs e) | |
{ | |
var space = (double) e.NewValue; | |
var obj = (DependencyObject) sender; | |
MarginSetter.SetMargin(obj, new Thickness(0, 0, space, 0)); | |
MarginSetter.SetLastItemMargin(obj, new Thickness(0)); | |
} | |
[UsedImplicitly] | |
public static void SetHorizontal(DependencyObject obj, double space) | |
{ | |
obj.SetValue(HorizontalProperty, space); | |
} | |
[UsedImplicitly] | |
public static void SetVertical(DependencyObject obj, double value) | |
{ | |
obj.SetValue(VerticalProperty, value); | |
} | |
private static void VerticalChangedCallback(object sender, DependencyPropertyChangedEventArgs e) | |
{ | |
var space = (double) e.NewValue; | |
var obj = (DependencyObject) sender; | |
MarginSetter.SetMargin(obj, new Thickness(0, 0, 0, space)); | |
MarginSetter.SetLastItemMargin(obj, new Thickness(0)); | |
} | |
public static readonly DependencyProperty VerticalProperty = | |
DependencyProperty.RegisterAttached("Vertical", typeof (double), typeof (Spacing), | |
new UIPropertyMetadata(0d, VerticalChangedCallback)); | |
public static readonly DependencyProperty HorizontalProperty = | |
DependencyProperty.RegisterAttached("Horizontal", typeof (double), typeof (Spacing), | |
new UIPropertyMetadata(0d, HorizontalChangedCallback)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment