Vadim's Weblog

Never stop learning.

Archive for the ‘WPF’ Category

WPF Margin demystified.

Posted by Vadim on October 13, 2008

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

Posted in .Net, C#, WPF, XAML | 2 Comments »

WPF Margin Property

Posted by Vadim on October 5, 2008

I finally decided to spend some time to learn WPF.  One of the thing I learned today is Margin property.

<Button Margin="10 0 10 5" />

Every control that derives from FrameworkElement class has this WPF_Margin property.

I’m not going to describe this property here. However, I want to share with you how I memorized the sequence of margin.  It goes like this: Left, Top, Right, Bottom.

The easiest way for me to remember is to start from Left and then go clock wise: Top, Right, Bottom.

There are two main reasons why I blog and both of them selfish.

First reason is because writing helps me remember and understand better new things I learn.

The second reason is that people who read my blog comment and correct any mistakes I make and that helps me to learn too.

I have a question for WPF gurus.  I understand that if all margins are the same (for example left, top, right, and bottom are equal to 5), it’s possible to assign margin like this:

<Button Margin="5" />

The both assignments with one number and four numbers make sense because Margin is of type Thickness  and this struct has two constructors:

public Thickness(double uniformLength)
public Thickness(double left, double top, double right, double bottom)

Here comes my question: I discovered that it’s possible to assign Margin declaratively with two numbers.

<Button Margin="10 5" />

How is it possible if Thickness doesn’t have a constructor with two parameters?
kick it on DotNetKicks.com

Posted in .Net, C#, WPF | 15 Comments »