Home > Software engineering >  Set Width property of an element as percentage of another element's width
Set Width property of an element as percentage of another element's width

Time:12-21

I have a Grid like this:

<Grid HorizontalAlignment="Stretch">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="2*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Text="Rank Percentage" Grid.Column="0" />
    <Rectangle Height="20" Grid.Column="1" Width="{x:Bind CurrentCar.RankPercentage, Mode=OneWay}"
</Grid>

I want the width of the rectangle to be proportional to the width of the column. The width of the Grid is not known during compile time (it depends on how user resizes the window of the app). For example: If Grid has Width 450, CurrentCar.RankPercentage = 80, Rectangle should have Width = 450 * (2/3) * (80/100)

I have tried to use a Converter with ConverterParameter = ActualWidth of the Grid, but it's not working.

CodePudding user response:

You can use the Grid's SizeChangedevent this:

private void TheGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
    double rectangleWidth = TheGrid.ActualWidth;
    rectangleWidth *= (2.0 / 3.0);
    rectangleWidth *= (CurrentCar.RankPercentage / 100.0);
    TheRectangle.Width = rectangleWidth;
}

But I think you should take a look at the ProgressBar control.

CodePudding user response:

You could use the valueConverter but you might need to modify the Converter a little bit. You could add a property to the Converter and bind with your root grid, then pass the element name as parameter to the Converter. Then you could get width value of the Grid inside the Converter. I've made a simple demo which you could try.

Xaml:

<Page.Resources>
    <local:MyValueConverter x:Key="MyValueConverter" UIParameter="{x:Bind MyGrid}" />
</Page.Resources>


<Grid x:Name="MyGrid" HorizontalAlignment="Stretch">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"></ColumnDefinition>
        <ColumnDefinition Width="2*"></ColumnDefinition>
    </Grid.ColumnDefinitions>
    <TextBlock Text="Rank Percentage" Grid.Column="0" />
    <Rectangle Height="20" Grid.Column="1" Fill="Red"
               Width="{x:Bind CurrentCar.RankPercentage, Mode=OneWay, Converter={StaticResource MyValueConverter}}"/>
</Grid>

MainPage.cs:

There might be a warning in this.Bindings.Update(). But actually, it does not matter

       public ViewModel CurrentCar { get; set; }
    public MainPage()
    {
        this.InitializeComponent();
        CurrentCar= new ViewModel();
        CurrentCar.RankPercentage = 0.5;
        this.Loaded  = MainPage_Loaded;
    }

    private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        this.Bindings.Update();
    }
}
public class ViewModel 
{
    public double RankPercentage { get; set; }
}

public class MyValueConverter : IValueConverter 
{
    public UIElement UIParameter { get; set; }
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        double rankPercentage = System.Convert.ToDouble(value);
        double rectangleWidth=0;

        if (UIParameter != null)
        {
            Grid grid = UIParameter as Grid;
            double gridWidth = grid.ActualWidth;
            rectangleWidth = gridWidth * (2.0 / 3.0) * rankPercentage;
            return rectangleWidth;
        }

        return rectangleWidth;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
  • Related