.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

Advertisements
.Net, XAML

Paste works differently in XAML files.

I finally found time to play with Silverlight 2.0 Beta 1.  Working with Visual Studio I got so used to be able to cut and paste a row without a selecting a line.  When you work with XAML, Ctrl-C will copy a line without a selecting a line (expected behavior).  However, when you try to paste (Ctrl-V), and your cursor is not at the beginning of the line, the text is inserted were your cursor is, breaking the existing line.  I have no idea why I haven’t notice it before when I worked with WPF and Silverlingt 1.0.  It works as expected with ASPX, HTML, and other files but behaves differently in XAML files.  I wonder why.