MadMaxIV
MadMaxIV

Reputation: 100

How to Bind to Height with "auto" value

Working with UWP means I cant use DIP values always. I rely on "auto" sizes, "Stretch" alignments, etc. I narrowed my problem to this:

How Can I Bind Height and Width of Element to Another Element, which has Height and Width "Auto"?

Sample:

<Grid.RowDefinitions>
            <RowDefinition x:Name="CardGriddRow1" Height="2*" />
            <RowDefinition x:Name="CardGrdidRow2" Height="1*" />
</Grid.RowDefinitions>

        <Rectangle Name="Rec1" Fill="Blue"  VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="auto" Height="auto" Grid.Row="1" Margin="20" />
        <Rectangle Name="Rec2" Fill="Yellow" Grid.Row="0" Height="{x:Bind Rec1.ActualHeight, Mode=OneWay  }" Width="{x:Bind Rec1.ActualWidth, Mode=OneWay }"  HorizontalAlignment="Left" VerticalAlignment="Top"  />

When using ActualHeight, I can use only OneWay mode. Height value is NaN. Rec2 will have 0 values but ActualHeight of Rec1 is more than 0.

Is there way to force Binding to take ActualHeight?

Upvotes: 0

Views: 1210

Answers (2)

jsmyth886
jsmyth886

Reputation: 531

I would try to avoid the SizeChanged event as much as possible as it fires so often when the screen is resized it can cause the UI to start freezing and drop in frame rate. Let the Xaml do as much of the work as possible. I've recreated the scenario you've shown in the link you attached in your comment using Xaml only. See screenshot:enter image description here

It may not be exactly the same as yours but with some styling it could be.

See code:

<Page>
  <Page.Resources>
    <Style TargetType="Rectangle">
      <Setter Property="VerticalAlignment"
              Value="Stretch"/>
      <Setter Property="HorizontalAlignment"
              Value="Stretch" />
    </Style>
  </Page.Resources>
  <Grid Background="Blue">
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>
  <Grid Grid.Row="0"
        Grid.RowSpan="2"
        Grid.Column="0"
        Grid.ColumnSpan="8">
    <Grid.RowDefinitions>
      <RowDefinition Height="*" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="3*" />
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>
    <Rectangle Grid.Row="0"
               Grid.Column="1"
               Fill="Red" />
    <Rectangle Grid.Row="0"
               Grid.Column="2"
               Fill="Yellow" />
  </Grid>
    <Rectangle Grid.Row="2"
               Grid.Column="0"
               Fill="Blue" />
    <Rectangle Grid.Row="2"
               Grid.Column="1"
               Fill="Red" />
    <Rectangle Grid.Row="2"
               Grid.Column="2"
               Fill="Green" />
    <Rectangle Grid.Row="2"
               Grid.Column="3"
               Fill="Yellow" />
    <Rectangle Grid.Row="2"
               Grid.Column="4"
               Fill="Brown" />
    <Rectangle Grid.Row="2"
               Grid.Column="5"
               Fill="Pink" />
    <Rectangle Grid.Row="2"
               Grid.Column="6"
               Fill="Purple" />
    <Rectangle Grid.Row="2"
               Grid.Column="7"
               Fill="Orange" />
  </Grid>
</Page>

Upvotes: 0

Sunteen Wu
Sunteen Wu

Reputation: 10627

How Can I Bind Height and Width of Element to Another Element, which has Height and Width "Auto"?

ActualHeight is a calculated property. For purposes of ElementName binding, ActualHeight does not post updates when it changes (due to its asynchronous and run-time calculated nature). Do not attempt to use ActualHeight as a binding source for an ElementName binding. If you have a scenario that requires updates based on ActualHeight, use a SizeChanged handler. Details please reference ActualHeight property.

Although updated your code snippet to use binding instead as follows, it seems like worked , but it is not reliable that you should not use it .

 <Rectangle Name="Rec1" Fill="Blue"  VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  Grid.Row="1" Margin="20" Height="auto" Width="auto" />
 <Rectangle Name="Rec2" Height="{Binding Path=ActualHeight,ElementName=Rec1}" Width="{Binding Path=ActualWidth,ElementName=Rec1}" HorizontalAlignment="Left" VerticalAlignment="Top"   Fill="Yellow" Grid.Row="0"/>

The correct way as the document mentioned, you could use SizeChanged, for example:

<Rectangle Name="Rec1" SizeChanged="Rec1_SizeChanged" Fill="Blue"  VerticalAlignment="Stretch" HorizontalAlignment="Stretch"  Grid.Row="1" Margin="20" Height="auto" Width="auto" />
<Rectangle Name="Rec2" Fill="Yellow" Grid.Row="0"  HorizontalAlignment="Left" VerticalAlignment="Top"  />

Code behind:

private void Rec1_SizeChanged(object sender, SizeChangedEventArgs e)
{
    Rec2.Height = Rec1.ActualHeight;
    Rec2.Width = Rec1.ActualWidth;
}

Upvotes: 1

Related Questions