.Net, C#, WPF, XAML

WPF Margin demystified.

In my previous post I asked a question about this line of code:

<Button Margin="10 5" />

Question:

In XAML we can assign margin to a control three different ways:

<Button Margin="5" />
<Button Margin="10 5" />
<Button Margin="10 5 10 10" />
  • The first line assigns left, top, right, and bottom margins with value 5.
  • The second line assigns left and right margins with value 10 but top and bottom with value 5.
  • The last line assigns left, right, and bottom with value 10 and top would have value 5.

If we try to do the same in the code behind, it would look like this:

button.Margin = new Thickness(5);
button.Margin = new Thickness(10, 5, 10, 10);

You can see in the code above that we have code for line 1 & 3 only.  I couldn’t find the way to create code behind for second line because there’s no Thickness constructor with two parameters.

Thanks to Rune Jacobsen & Sam who provided some clues in comments to my previous article.

Answer:

After I read Sam’s comment:

The converter at work here is a ThicknessConverter which parses the input string and attempts to map the values given in the string to one of the Thickness object constructor overloads.

, I used .NET Reflector to analyze ThicknesseConverter class.

ThicknesseConveter has a public method ConvertFrom that calls internal method FromString.

public override object ConvertFrom(
    ITypeDescriptorContext typeDescriptorContext,
    CultureInfo cultureInfo,
    object source)
{
     . . .
    if (source is string)
    {
        return FromString((string) source, cultureInfo);
    }
     . . .
}

FromString method is responsible for parsing string values like “10, 5, 10, 10” and converting them into Thickness.

It means that this code

<Button Margin="10 5" />

will be converted by FromString method into:

new Thickness(numArray[0], numArray[1], numArray[0], numArray[1]);

Bellow is a switch statement in FromString method that explains the magic.

internal static Thickness FromString(string s, CultureInfo cultureInfo)
{
     . . .
    switch (index)
    {
        case 1:
            return new Thickness(numArray[0]);
        case 2:
            return new Thickness(numArray[0], numArray[1], numArray[0], numArray[1]);
        case 4:
            return new Thickness(numArray[0], numArray[1], numArray[2], numArray[3]);
    }
     . . .
}

If you want to assign a margin with two doubles from the code behind, you can do it like this:

button.Margin =
    (Thickness)new ThicknessConverter()
        .ConvertFrom(null, CultureInfo.CurrentCulture, "5, 10");

Mystery is solved.

kick it on DotNetKicks.com

2 thoughts on “WPF Margin demystified.

  1. Thanks for breaking down the Margin object. It seems that Margin is readonly property at least for User Control. Does this mean that one can not alter Margin during runtime ? Your presented code, does it actually compile ?

    Cannot modify the return value of ‘System.Windows.FrameworkElement.Margin’ because it is not a variable

  2. Pingback: Reisebericht

Leave a reply to Sergey Malyan Cancel reply