0
votes

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?

2
Can you give more information about why you need to be able to do this, because the code shown and the description given doesn't really explain why you would need to do this? (There may be a way for you to set up your xaml without having to set the Height and Width to that of another element) - jsmyth886
@ jsmyth886 I'm making a simple card game. Sample Picture (a simple placeholder really): link In the bottom row there are 8 cards in the grid, which has allways fill the entire width of the screen. These cards can be in two rows, one row above the other, when narrow screen. This is handled by VisualStateManager. In the Upper middle, there are two packs of cards, which are the same size as the bottom cards. I want to do this only in XAML, but binding is not working properly. I was hoping, I'm missing something. - MadMaxIV

2 Answers

1
votes

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

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>