如何删除文本标签内不需要的填充?

时间:2017-08-30 09:48:04

标签: wpf xaml

我有这样的标签:

 <Grid Name="grid_footer" Grid.Row="2" ShowGridLines="True">
                <Grid.RowDefinitions>
                    <RowDefinition Height="3.4*" />
                    <RowDefinition Name="row_text" Height="3.2*" />
                    <RowDefinition Height="3.4*" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0.38*" />
                    <ColumnDefinition Width="9.62*" />
                </Grid.ColumnDefinitions>

                <!-- project location label -->
                <Label  Name ="FileLocationLabel" Content="TEST"  Foreground="Black" Background="Beige" FontWeight="Bold" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="1"  Grid.RowSpan="1" HorizontalAlignment="Left" Padding="0" FontSize="{Binding ElementName=row_text, Path=ActualHeight}"/>


            </Grid>

enter image description here

正如你所看到的,底部仍然有一些不需要的填充物,我已经尝试了几乎所有东西来移除它但我不能。我只想让字体从行的顶部延伸到底部。

3 个答案:

答案 0 :(得分:2)

首先,请尝试以下方法:

  • 将文字包装在容器中以获取ActualHeight,因为这不是来自RowDefinition
  • TextBlock.LineHeightTextBlock.LineStackingStrategy设置添加到标签中(从https://stackoverflow.com/a/7568216/5265292中获取)
  • 尝试不同的字体...例如,当我设置FontFamily="Arial"时,我得到的间距细节与默认字体不同。

<Border
    x:Name="container1"
    Grid.Row="1" Grid.Column="1"
    VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Padding="0" Margin="0" BorderThickness="0">
    <Label
        Name ="FileLocationLabel"
        Content="TESTg"
        Foreground="Black" Background="Beige"
        FontWeight="Bold"
        HorizontalAlignment="Left"
        Padding="0" Margin="0"
        TextBlock.LineHeight="{Binding ElementName=container1,Path=ActualHeight}"
        TextBlock.LineStackingStrategy="BlockLineHeight"
        FontSize="{Binding ElementName=container1,Path=ActualHeight}"/>
</Border>

如果您需要更精确的字体大小调整,可能需要计算特定字体设置的实际文字大小,类似于此答案https://stackoverflow.com/a/15982149/5265292

注意我在测试内容中添加了"g",因为它使用了文本空间的下半部分,而"TEST"

将保持未使用状态

我决定仔细研究一下这个问题,并提出以下转换器来确定字体大小和lineheight,以支持不同的文本和字体。

/// <summary>
/// Values:
/// - text to be rendered
/// - available height
/// - framework element with values for fontfamily etc
/// 
/// By default, returns a font size for a given text to fit into available height
/// With parameter = "lineheight", produces the lineheight for a given text and font size
/// </summary>
public class FontSizeProvider : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string text = values[0] as string;
        double height = System.Convert.ToDouble(values[1]);
        FrameworkElement f = values[2] as FrameworkElement;

        if (height <= 0.0)
        {
            height = 10;
        }

        var param = parameter as string;

        // (1) in order to compute the LineHeight, take the font size, produce formatted text
        //   and determine the LineHeight based on available space and the size of text below the baseline
        // (2) in order to compute the fontsize, take the container height, produce formatted text
        //   and scale the font depending on the actual text size
        double fsize = param == "lineheight" ? TextBlock.GetFontSize(f) : height;

        FontFamily family = TextBlock.GetFontFamily(f);
        FontStyle style = TextBlock.GetFontStyle(f);
        FontWeight weight = TextBlock.GetFontWeight(f);
        FontStretch stretch = TextBlock.GetFontStretch(f);

        // produce the formatted text
        var formattedText = new FormattedText(text, culture,
            f.FlowDirection,
            new Typeface(family, style, weight, stretch),
            fsize, Brushes.Black);

        // get the result
        if (param == "lineheight")
        {
            var afterBaseline = formattedText.Height - formattedText.Baseline + formattedText.OverhangAfter;
            // for some reason, the desired line height needs to be scaled according to the font family line sizes
            var scalingFactor = family.LineSpacing / family.Baseline;
            var lineHeightResult = (height - afterBaseline) * scalingFactor;
            return System.Convert.ChangeType(lineHeightResult, targetType);
        }
        else
        {
            var fontSizeResult = height * height / formattedText.Extent;
            return System.Convert.ChangeType(fontSizeResult, targetType);
        }
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

资源实例:

<local:FontSizeProvider x:Key="fontSizeProvider"/>

用法:

<Border x:Name="container1"
        Grid.Row="1" Grid.Column="1"
        VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
        Padding="0" Margin="0" BorderThickness="0">

    <Label
        Content="TÉ"
        Foreground="Black" Background="Beige"
        HorizontalAlignment="Left"
        Padding="0" Margin="0"
        TextBlock.LineStackingStrategy="BlockLineHeight">
        <Label.FontSize>
            <MultiBinding Converter="{StaticResource fontSizeProvider}">
                <Binding RelativeSource="{RelativeSource Self}" Path="Content"/>
                <Binding ElementName="container1" Path="ActualHeight"/>
                <Binding RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </Label.FontSize>
        <TextBlock.LineHeight>
            <MultiBinding Converter="{StaticResource fontSizeProvider}" ConverterParameter="lineheight">
                <Binding RelativeSource="{RelativeSource Self}" Path="Content"/>
                <Binding ElementName="container1" Path="ActualHeight"/>
                <Binding RelativeSource="{RelativeSource Self}"/>
            </MultiBinding>
        </TextBlock.LineHeight>
    </Label>

</Border>

缩放字体大小,以便将实际文本与实际字体放大以填充容器的高度。这意味着,对于相同的容器高度,文本"Ég"(较小的字体,因为文本使用很多高度)和"ace"(较大的字体,因为所有字母都是较小的高度)之间的字体大小会有所不同。

在计算LineHeight时我遇到了一个奇怪的问题:我不得不将可用高度乘以1.22(对于Segoe UI字体),以使文本的基线出现在底部可用空间。这对其他一些字体并不适用。经过一些测试后,我发现每个字体的正确比例因子由fontfamily.LineSpacing / fontfamily.Baseline给出。

解决了缩放因子问题后,该方法非常简单:计算在基线下方渲染的文本高度,并根据文本高度减去下面的额外空间来调整线高度。

答案 1 :(得分:0)

VerticalAlignment属性设置为Top

<Label Name ="FileLocationLabel" ... VerticalAlignment="Top" />

答案 2 :(得分:-1)

尝试使用ViewBox来展开Label

<Viewbox Grid.Row="1" Grid.Column="1"  StretchDirection="Both" Stretch="Uniform" HorizontalAlignment="Left">
        <Label Name ="FileLocationLabel" Content="TEST"
                   Foreground="Black" Background="Beige" FontWeight="Bold"
                   HorizontalAlignment="Left" VerticalAlignment="Stretch"  Padding="0"/>
</Viewbox>