descf
descf

Reputation: 1312

How do I set the size of elements in a user control according to property settings on the user control?

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

Answers (4)

Rob
Rob

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

AnthonyWJones
AnthonyWJones

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

Haris Hasan
Haris Hasan

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;
    }

enter image description here

Upvotes: 0

Elad Katz
Elad Katz

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

Related Questions