简体   繁体   中英

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>

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.

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>

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.

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

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM