如果元素小于最大高度,则使元素占据网格中的整个空间,否则固定到底部



我想完成以下任务:

  • Grid元素的右侧有一个徽章。
  • 徽章的最大高度应为 33px。
  • 如果Grid高度本身小于 33px,则徽章应占用整个可用空间,并且大小与Grid相同。
  • 如果Grid高度本身超过 33px
  • ,则徽章应固定在底部且高度为 33px。

这是我目前拥有的代码:

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- ... -->
<Grid Grid.Column="2">
<Border Width="60"
MaxHeight="33"
CornerRadius="0 0 3 0"
Background="#FFD20B0B">
<TextBlock FontSize="13"
FontWeight="Bold"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontFamily="Arial"
Foreground="#FFFFFFFF">
<Span>Broken</Span>
</TextBlock>
</Border>
</Grid>
</Grid>

这满足了除最后一个要求之外的所有要求。无论我做什么,如果父Grid大小大于 33px,徽章都会固定在中心。在这种情况下,我如何将其固定在底部?

附言如果我使用VerticalAlignment="Bottom",我将失去第三个要求 - 当Grid的大小小于 33px 时,徽章不会变成Grid的高度(例如Grid大小 = 20px)。

遗憾的是,WPF 没有内置的 XAML 语法来执行大于等比较。您可以为此创建一个自定义值转换器,例如,如果值大于给定参数,则返回true,否则false

public class IsGreaterThanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (!(value is double doubleValue) ||
!(parameter is string parameterText) ||
!double.TryParse(parameterText, out var doubleParameter))
return Binding.DoNothing;
return doubleValue > doubleParameter;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return new InvalidOperationException();
}
}

这个想法是将父GridActualHeight绑定到一个DataTrigger中,该使用上面的转换器检查它是否大于阈值(此处33)。根据这一点,它设置BorderVerticalAlignmentHeightVerticalAlignment的默认值为Stretch,如果实际高度小于或等于33(转换器返回false),则设置该值。

<Grid>
<Grid.Resources>
<local:IsGreaterThanConverter x:Key="IsGreaterThanConverter"/>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- ... -->
<Grid Grid.Column="2">
<Border Width="60"
MaxHeight="33"
CornerRadius="0 0 3 0"
Background="#FFD20B0B">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type Grid}}, Converter={StaticResource IsGreaterThanConverter}, ConverterParameter=33}" Value="True">
<Setter Property="Height" Value="33"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</DataTrigger>
</Style.Triggers>
</Style> 
</Border.Style>
<TextBlock FontSize="13"
FontWeight="Bold"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontFamily="Arial"
Foreground="#FFFFFFFF">
<Span>Broken</Span>
</TextBlock>
</Border>
</Grid>
</Grid>

不要忘记转换器需要在范围内的资源字典中实例化,在Grid.Resources中。当然,如果需要,您也可以将样式提取到资源字典中。

您可以将边框的高度绑定到网格的实际高度。结合您的MaxHeight和VerticalAligning将为您提供所需的内容。

<Grid x:Name="RootGrid" Grid.Column="2">
<Border Width="60"
MaxHeight="33"
CornerRadius="0 0 3 0"
Background="#FFD20B0B"
VerticalAlignment="Bottom"
Height="{Binding ActualHeight, ElementName=RootGrid}">
<!-- ... -->
</Border>
</Grid>

最新更新