Reputation: 1312
To make this simple: I have a user control that consists of 2 rectangles. At design time the user of the control sets the width of the user control and a default value for one of the rectangles which is a property of the user control. I want to treat the default value as a percentage and set the width of one of the rectangles to that percentage of the other rectangles width. The kind of difficulty I'm having is that I cannot get the width of the outer rectangle to set the other rectangles width as a percentage of (because everything seems to be 0 or NaN). Here's some code:
User Control:
<Grid x:Name="LayoutRoot" Background="White">
<Rectangle x:Name="OuterRectangle" Fill="Red"/>
<Rectangle x:Name="InnerRectangle" Fill="Blue"/>
</Grid>
User Control code behind:
public partial class ucRectangles : UserControl
{
public Double Percent { get; set; }
public ucRectangles()
{
InitializeComponent();
InnerRectangle.Width = Percent / 100 * OuterRectangle.ActualWidth;
}
}
Main Page:
<Grid x:Name="LayoutRoot" VerticalAlignment="Center">
<local:ucRectangles Width="400" Height="40" Percent="50"/>
</Grid>
Upvotes: 1
Views: 1668
Reputation: 209
I know this seems answered already, but here's something similar I did last year for creating simple bar charts. Just bind your percentage to the "Content" property and you'll get a auto-resizing bar without all the extra code...
<ContentPresenter Content="0.3" Height="30"> <!-- Bind the "Content" to your percentage -->
<ContentPresenter.ContentTemplate>
<DataTemplate>
<Grid Background="YellowGreen">
<Rectangle Fill="Purple" Margin="0,5,0,5" HorizontalAlignment="Stretch" RenderTransformOrigin="0.5,0.5">
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="#FFFFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="{Binding}"/>
<GradientStop Color="#00000000" Offset="{Binding}"/>
<GradientStop Color="#00000000" Offset="1"/>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Grid>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
Upvotes: 0
Reputation: 189457
Why don't you get the Grid to do all this for you that is what its good at:-
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="50*" />
</Grid.ColumnDefinitions>
<Rectangle x:Name="OuterRectangle" Fill="Red" Grid.ColumnSpan="2"/>
<Rectangle x:Name="InnerRectangle" Fill="Blue" />
</Grid>
Now just fiddle with the star values of the column definitions, here is my implementation of the Percent
dependency property:-
#region public double Percent
public double Percent
{
get { return (double)GetValue(PercentProperty); }
set { SetValue(PercentProperty, value); }
}
public static readonly DependencyProperty PercentProperty =
DependencyProperty.Register(
"Percent",
typeof(double),
typeof(ShowCase1),
new PropertyMetadata(50.0, OnPercentPropertyChanged));
private static void OnPercentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ShowCase1 source = d as ShowCase1;
double percent = (double)e.NewValue;
source.LayoutRoot.ColumnDefinitions[0].Width = new GridLength(percent, GridUnitType.Star);
source.LayoutRoot.ColumnDefinitions[1].Width = new GridLength(100 - percent, GridUnitType.Star);
}
#endregion public double Percent
Note its the last two lines where the magic happens.
Upvotes: 1
Reputation: 30097
Handle (user control's) LayoutRoot's loaded event and move code inside it.
User Control XAML
<Grid x:Name="LayoutRoot" Background="White" Loaded="LayoutRoot_Loaded">
User Control Code Behind
private void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
InnerRectangle.Width = Percent / 100 * OuterRectangle.ActualWidth;
}
Upvotes: 0
Reputation: 7591
ActualWidth would only be relevant after the Measure pass has taken place. You're trying to do it in the C-tor, which would be WAY before the Measure is happening.
Try and use the Event LayoutUpdated, which is bound to happen after the layout process finished.
Upvotes: 0