I can set margins individually in code but how do I do it in XAML, e.g. how do I do this:
PSEUDO-CODE:
<StackPanel Margin.Top="{Binding TopMargin}">
I can set margins individually in code but how do I do it in XAML, e.g. how do I do this:
PSEUDO-CODE:
<StackPanel Margin.Top="{Binding TopMargin}">
You can't define just the Top margin with a binding, because Margin
is of type Thickness
which isn't a dependency object. However you could use a MultiValueConverter
that would take 4 margin values to make 1 Thickness objects
Converter :
public class ThicknessMultiConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double left = System.Convert.ToDouble(values[0]);
double top = System.Convert.ToDouble(values[1]);
double right = System.Convert.ToDouble(values[2]);
double bottom = System.Convert.ToDouble(values[3]);
return new Thickness(left, top, right, bottom);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
Thickness thickness = (Thickness)value;
return new object[]
{
thickness.Left,
thickness.Top,
thickness.Right,
thickness.Bottom
};
}
#endregion
}
XAML :
<StackPanel>
<StackPanel.Margin>
<MultiBinding Converter="{StaticResource myThicknessConverter}">
<Binding Path="LeftMargin"/>
<Binding Path="TopMargin"/>
<Binding Path="RightMargin"/>
<Binding Path="BottomMargin"/>
</MultiBinding>
</StackPanel.Margin>
</StackPanel>
Use a converter, the sample code below will convert the double you are binding to to a thickness. It will set the "Top" of the thickness to the bound field. You could optionally use a ConverterParameter to determine if you are binding to left, top, right, or bottom.
<StackPanel Margin="{Binding TopMargin, Converter={StaticResource MyThicknessConverter}">
.
public class ThicknessSingleValueConverter : IValueConverter
{
override Convert(...)
{
return new Thickness(0, (double)object, 0, 0);
}
//etc...
The key is to realize that setting it in code like this:
sp2.Margin = new System.Windows.Thickness{ Left = 5 };
is equivalent to:
sp2.Margin = new System.Windows.Thickness{ Left = 5, Top = 0, Right = 0, Bottom = 0 };
You can't set just a single value in a Thickness
instance through either code or XAML. If you don't set some of the values, they will be implicitly zero. Therefore, you can just do this to convert the accepted code sample in your other question to a XAML equivalent:
<StackPanel Margin="{Binding TopMargin, Converter={StaticResource MyConverter}}"/>
where MyConverter
just returns a Thickness
that sets only the Top
and leaves all other values as zero.
Of course, you could write your own control that does expose these individual values as dependency properties to make your code a little cleaner:
<CustomBorder TopMargin="{Binding TopMargin}">
</CustomBorder>
HTH, Kent
Isn't this what you're looking for?
<StackPanel Margin="0,10,0,0" />
The first value is Left margin, then Top, then Right, and last but not least Bottom.
I'm not sure if you want to bind it to something, but if not, that'll work.
I thought You could use the property syntax, from MSDN:
<object.Margin>
<Thickness Top="{Binding Top}"/>
</object.Margin>
Than you won't need any converter
But the Top is not DependancyProperty - back to converter
What would be nice is to be able to do this by specifying something like the code example below.
<StackPanel Margin=",10,,">
Unfortunately this capability doesn't seem to exist by default in WPF and it's a shame because it requires developers to hard code known default values in a way that later makes it more difficult to skin or theme an application.
The best solution that I can think of at this point is using a converter, but the amount of extra code you have to produce to introduce this is not ideal.