【问题标题】:How to Bind to Height with "auto" value如何使用“自动”值绑定到高度
【发布时间】:2017-11-08 21:07:27
【问题描述】:

使用 UWP 意味着我不能总是使用 DIP 值。我依靠“自动”尺寸、“拉伸”对齐等。 我把我的问题缩小到这个:

如何将元素的高度和宽度绑定到另一个高度和宽度为“自动”的元素?

示例:

<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"  />

使用 ActualHeight 时,我只能使用 OneWay 模式。高度值为 NaN。 Rec2 的值为 0,但 Rec1 的 ActualHeight 大于 0。

有没有办法强制 Binding 采用 ActualHeight?

【问题讨论】:

  • 您能否提供更多信息,说明您为什么需要这样做,因为显示的代码和给出的描述并不能真正解释您为什么需要这样做? (您可能有一种方法可以设置您的 xaml,而无需将高度和宽度设置为另一个元素的高度和宽度)
  • @jsmyth886 我正在制作一个简单的纸牌游戏。示例图片(实际上是一个简单的占位符):link 在最下面一行的网格中有 8 张卡片,它们始终占据了整个屏幕的宽度。当屏幕窄时,这些卡片可以排成两排,一排在另一排之上。这由 VisualStateManager 处理。上中部有两包牌,与底牌大小相同。我只想在 XAML 中执行此操作,但绑定无法正常工作。我希望,我错过了一些东西。

标签: xaml uwp windows-10


【解决方案1】:

如何将元素的高度和宽度绑定到另一个高度和宽度为“自动”的元素?

ActualHeight 是一个计算属性。出于ElementName 绑定的目的,ActualHeight 在更改时不会发布更新(由于其异步和运行时计算性质)。不要尝试将ActualHeight 用作ElementName 绑定的绑定源。如果您有需要基于ActualHeight 进行更新的场景,请使用SizeChanged 处理程序。详情请参考ActualHeight属性。

虽然将您的代码 sn-p 更新为如下使用绑定,但似乎有效,但您不应该使用它是不可靠的。

 <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"/>

文档中提到的正确方法,可以使用SizeChanged,例如:

<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"  />

后面的代码:

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

【讨论】:

  • 谢谢你的解释,它帮助我理解了这个问题。第一个解决方案适用于页面的启动,但之后它不会调整矩形的大小。对于 SizeChanged,如果不是真的需要,我不想使用事件处理程序进行图形布局。
  • @MadMaxIV 在这种情况下,我会在下面查看我的答案。它展示了您如何设置您的 Xaml,以便在调整应用程序大小的同时,理论上它应该“正常工作”而没有任何 SizeChanged 的​​讨厌。
【解决方案2】:

我会尽量避免SizeChanged 事件,因为它在调整屏幕大小时经常触发,可能导致 UI 开始冻结并降低帧速率。让 Xaml 完成尽可能多的工作。我仅使用 Xaml 重新创建了您在评论中附加的链接中显示的场景。见截图:

它可能与您的不完全相同,但可以通过一些样式来实现。

见代码:

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

【讨论】:

  • 这个解决方案,将页面拆分为单元格以匹配顶行和底行,有点难以使用,因为页面布局会复杂得多,但我可以玩它,有很多列和行跨度。尽管如此,我还是希望从 XAML 中获得更好的可能性。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-01-25
  • 2012-09-13
  • 1970-01-01
  • 1970-01-01
  • 2015-05-23
  • 2020-10-26
  • 2014-06-20
  • 1970-01-01
相关资源
最近更新 更多