Alan Baljeu Alan Baljeu - 4 months ago 14
C# Question

How do I manage the width of controls through UserControl parameters?

In short, the goal is to propagate LabelWidth to its children in my UserControl class, PropertyView. See this fragment:

<TabItem.Header>Press</TabItem.Header>
<TabItem.DataContext>
<Binding XPath="press_information"/>
</TabItem.DataContext>
<W3V:PropertyView LabelWidth="200"></W3V:PropertyView>


ANSWER (credit to Athari for his part). To make it work, I needed two elements: In C#, a dependency property:

public double LabelWidth
{ get { return (double)this.GetValue(LabelWidthProperty); }
set { this.SetValue(LabelWidthProperty, value); }
}
public static readonly DependencyProperty LabelWidthProperty =
DependencyProperty.Register(
"LabelWidth", typeof(double), typeof(PropertyView), new PropertyMetadata(100.0)
);


In XAML, the following binding syntax:

<W3V:SimpleControl x:Name="simple" Content="{Binding}"
LabelWidth="{Binding LabelWidth,
RelativeSource={RelativeSource AncestorType=W3V:PropertyView}}" />


What didn't work (my original problem):

See the ????? below in the XAML code. I have NO IDEA what I can put in to make it so the SimpleControl will get a LabelWidth assigned, so that it will set its TextBlock's Width property.

I don't even care what approach is taken, it just needs to deal with the fact that PropertyView is bound to an XML object so it can display its properties, and LabelWidth needs to be a property the control-user sets that gets shoved down into the control. LabelWidth will vary depending on what object is being displayed, so it can't be global.

<UserControl x:Class="W3.Views.PropertyView" ... >

<UserControl.Resources>
</UserControl.Resources>
<StackPanel Margin="2" CanVerticallyScroll="true">
<Border Height="22">
<TextBlock VerticalAlignment="Bottom"
Text="{Binding XPath=@label}"
FontSize="16" FontWeight="Bold" />
</Border>
<ItemsControl ItemsSource="{Binding XPath=*}" Margin="20,0,0,0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<W3V:SimpleControl x:Name="simple"
Content="{Binding}"
LabelWidth=?????? />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

</StackPanel>

</UserControl>


C#:

public partial class PropertyView : UserControl
{
public double LabelWidth
{
get { return (double)this.GetValue(LabelWidthProperty); }
set { this.SetValue(LabelWidthProperty, value); }
}
public static readonly DependencyProperty LabelWidthProperty =
DependencyProperty.Register(
"LabelWidth2", typeof(double), typeof(PropertyView), new PropertyMetadata(0.0)
);
public PropertyView()
{
InitializeComponent();


}
}


I've searched extensively for a solution that deals with this combination of circumstances, tried many things without success (well, success for simpler situations, but not this), and I'm at a loss here.

Answer

So, you just need to bind SimpleControl.LabelWidth to PropertyView.LabelWidth? It can be achieved this way:

<W3V:SimpleControl
    LabelWidth="{Binding Path=LabelWidth,
                     RelativeSource={RelativeSource AncestorType=PropertyView}}"

P.S. Your dependency property is registered as "LabelWidth2" (typo?). And new PropertyMetadata(0.0) is redundant, as default(double) == 0.0.