Skip to content

Instantly share code, notes, and snippets.

@angularsen
Created January 17, 2015 12:19
Show Gist options
  • Select an option

  • Save angularsen/90040fb174f71c5ab3ad to your computer and use it in GitHub Desktop.

Select an option

Save angularsen/90040fb174f71c5ab3ad to your computer and use it in GitHub Desktop.

Revisions

  1. angularsen created this gist Jan 17, 2015.
    73 changes: 73 additions & 0 deletions MarginSetter.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,73 @@
    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));
    }
    }
    55 changes: 55 additions & 0 deletions Spacing.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,55 @@
    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));
    }
    }
    14 changes: 14 additions & 0 deletions example.xaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,14 @@
    <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>