views:

33

answers:

3

Hi all

What's the best way to add margin between columns or rows in a WPF or Silverlight grid?

  1. Add fixed width/height columns/rows to the grid
  2. Add margin to the grid child controls
  3. Anything else?

Thanks in advance

A: 

I'd go with option 2.

Jackson Pope
Thanks for sharing your opinion, any perticular reason why you'd choose 2?
vc 74
It just feels 'cleanest' to me. What you want is a margin around the controls - so adding a margin seems the best way to do it. Option 1 could cause problems if you change the contents of the grid.
Jackson Pope
True but imagine the case where you replace a child control with a StackPanel for instance, you have to move the margin from the child control to the StackPanel whereas using option 1 would be easier. Thanks for your comment anyway.
vc 74
Good point. I'd still go with Option 2 though :)
Jackson Pope
A: 

If you don't mind deriving your own control from the Grid and using that instead, you can do it quite easily. Since it seems like a good idea I quickly whipped up this (mostly untested and quite ugly!) code:

/// <summary>
/// Enhanced Grid that can automatically apply a padding to all its children.
/// </summary>
public class PaddedGrid : Grid
{

    /// <summary>
    /// Gets or sets a padding value to apply as the margin to all children.
    /// If left to default (null or 'zero' Thickness) the margins of the children are not modified.
    /// </summary>
    public Thickness? Padding
    {
        get { return (Thickness?)GetValue(PaddingProperty); }
        set { SetValue(PaddingProperty, value); }
    }

    public static readonly DependencyProperty PaddingProperty =
        DependencyProperty.Register("Padding", typeof(Thickness?), typeof(PaddedGrid), new PropertyMetadata(PaddingChanged));

    private bool HasPadding()
    {
        return Padding.HasValue && Padding.Value != default(Thickness);
    }

    private static void PaddingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var g = d as PaddedGrid;
        if (g != null)
        {
            if (!g.HasPadding()) return;
            for (int i = 0; i < g.VisualChildrenCount; i++)
            {
                var v = g.GetVisualChild(i);
                var c = v as FrameworkElement;
                if (c == null || c is GridSplitter) continue;
                c.Margin = (Thickness)e.NewValue;
            }
        }
    }

    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
    {
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);
        if (!HasPadding()) return;
        if (visualAdded != null)
        {
            var fe = visualAdded as FrameworkElement;
            if (fe != null) fe.Margin = this.Padding.Value;
        }
    }
}
Alex Paven
Thanks for your answer, the thing is I don't want the margin to be automatic but to have control on which columns and rows it shoud apply to.
vc 74
Well, you can always extend it to your liking. For example you could accept separate values for rows and columns as strings, and in the strings you could put comma-separated values that represent the margins. However, since the grid doesn't have the rows and columns as 'children', you'll need to determine on which row and column a child visual is positioned (using the Grid.Row and Grid.Column attached properties). The sky's the limit, but of course it doesn't make much sense to create your own mini grid alignment framework unless you are really gonna use it in a _lot_ of places.
Alex Paven
I agree the most with your last statement: "of course it doesn't make much sense to create your own mini grid alignment framework unless you are really gonna use it in a lot of places." This solution, while it may have its place, is much more complex than most solutions need be, which may make it more difficult to maintain (especially when you start adding parsable parameters, etc.)
Wonko the Sane
A: 

It depends, really, on your design, and is a matter of your own tastes. The biggest thing is to be consistent.

I think it's perfectly acceptable to put a fixed width "spacer" column or row in most cases - then you don't have to worry about maintenance later (either by you or somebody else).

The thing to watch out for is setting things twice (i.e. both a margin and fixed width column). It's not too big a problem if you are using all the same kind of control, but it could get a little ugly if you use different kinds of controls that have Styles applied to them that include Margins and/or Padding.

Wonko the Sane