对齐控件中文本的底部 [英] Align bottoms of text in controls

查看:19
本文介绍了对齐控件中文本的底部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下片段:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center">            
            <Label Content="Name:"/>
            <Label Content="Itzhak Perlman" FontSize="44"/>
        </StackPanel>
    </Grid>
</Window>

呈现以下内容:

Renders the following:

有什么方法可以设置标签的样式,使其文本底部对齐?
我对 TextBlocks 也有同样的问题.

Is there any way I can set in the Labels' styles so that their text bottoms should be aligned?
I have the same question with TextBlocks as well.

注意:由于我一直在为这个问题苦苦挣扎,请只发布您知道有效的某些答案.
我已经尝试过:VerticalAlignment、VerticalContentAlignment、Padding、Margin.还有什么我不知道的吗?

NOTE: since I've been struggling with this issue for a while, please post only certains answers that you know that work.
I already tried: VerticalAlignment, VerticalContentAlignment, Padding, Margin. Is there anything else I am not aware of?

我已阅读这篇帖子,但它没有谈论不同字体大小的场景.

I've read this post, but it doesn't talk about a scenario of different font size.

更新:问题是,即使 Padding 设置为 0,在 ContentPresenter 区域内,字体周围仍然存在不确定的空间.此空间因字体大小而异.如果我能控制这个空间,我会处于更好的境地.

UPDATE: The problem is, that even Padding is set to 0 there is still an indeterminate space around the font, within the ContentPresenter area. this space varies on the font size. If I could control this space I would be in a better situation.

谢谢

推荐答案

没有唯一的 XAML 解决方案,您必须使用背后的代码.此外,即使使用代码隐藏,也没有通用的解决方案,因为如果您的文本是多行的怎么办?在这种情况下应该使用哪个基线?或者如果您的模板中有多个文本元素怎么办?比如一个header和一个content,或者更多,哪个baseline呢?

There is no XAML only solution, you have to use code behind. Also, even with code-behind, there's no general solution for this, because what if your text is multi-line? Which baseline should be used in that case? Or what if there are multiple text elements in your template? Such as a header and a content, or more, which baseline then?

简而言之,最好的办法是使用顶部/底部边距手动对齐文本.

In short, your best bet is to align the text manually using top/bottom margins.

如果你愿意假设你有一个文本元素,你可以通过实例化一个 FormattedText 对象来计算基线到元素顶部的像素距离现有文本元素的相同属性.FormattedText 对象具有保存该值的 double Baseline 属性.请注意,您仍然需要手动输入边距,因为该元素可能不会正好位于其容器的顶部或底部.

If you're willing to make the assumption that you have a single text element, you can figure out the pixel distance of the baseline from the top of the element by instantiating a FormattedText object with all the same properties of the existing text element. The FormattedText object has a double Baseline property which holds that value. Note that you still would have to manually enter a margin, because the element might not sit exactly against the top or bottom of its container.

请参阅此 MSDN 论坛帖子:文本框基线

See this MSDN forum post: Textbox Baseline

这是我编写的一种提取该值的方法.它使用反射来获取相关属性,因为它们对于任何单个基类都是不通用的(它们分别定义在 ControlTextBlockPageTextElement 和其他的).

Here's a method I wrote that extracts that value. It uses reflection to get the relevant properties because they are not common to any single base class (they are defined separately on Control, TextBlock, Page, TextElement and maybe others).

public double CalculateBaseline(object textObject)
{
    double r = double.NaN;
    if (textObject == null) return r;

    Type t = textObject.GetType();
    BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;

    var fontSizeFI = t.GetProperty("FontSize", bindingFlags);
    if (fontSizeFI == null) return r;
    var fontFamilyFI = t.GetProperty("FontFamily", bindingFlags);
    var fontStyleFI = t.GetProperty("FontStyle", bindingFlags);
    var fontWeightFI = t.GetProperty("FontWeight", bindingFlags);
    var fontStretchFI = t.GetProperty("FontStretch", bindingFlags);

    var fontSize = (double)fontSizeFI.GetValue(textObject, null);
    var fontFamily = (FontFamily)fontFamilyFI.GetValue(textObject, null);
    var fontStyle = (FontStyle)fontStyleFI.GetValue(textObject, null);
    var fontWeight = (FontWeight)fontWeightFI.GetValue(textObject, null);
    var fontStretch = (FontStretch)fontStretchFI.GetValue(textObject, null);

    var typeFace = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);

    var formattedText = new FormattedText(
        "W", 
        CultureInfo.CurrentCulture, 
        FlowDirection.LeftToRight, 
        typeFace, 
        fontSize, 
        Brushes.Black);

    r = formattedText.Baseline;

    return r;
}

Shimmy,为了回应你的评论,我不相信你真的尝试过这个解决方案,因为它有效.举个例子:

Shimmy, in response to your comment, I don't believe you've actually tried this solution, because it works. Here's an example:

这是 XAML:

<StackPanel>
    <StackPanel.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Margin" Value="0,40,0,0"/>
        </Style>
    </StackPanel.Resources>
    <StackPanel Orientation="Horizontal">
        <TextBlock Name="tb1" Text="Lorem " FontSize="10"/>
        <TextBlock Name="tbref" Text="ipsum"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Name="tb2" Text="dolor "  FontSize="20"/>
        <TextBlock Text="sit"/>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock Name="tb3" Text="amet "  FontSize="30"/>
        <TextBlock Text="consectetuer"/>
    </StackPanel>
</StackPanel>

这是实现这一目标的代码

And here's the code behind that achieves this

double baseRef = CalculateBaseline(tbref);
double base1 = CalculateBaseline(tb1) - baseRef;
double base2 = CalculateBaseline(tb2) - baseRef;
double base3 = CalculateBaseline(tb3) - baseRef;
tb1.Margin = new Thickness(0, 40 - base1, 0, 0);
tb2.Margin = new Thickness(0, 40 - base2, 0, 0);
tb3.Margin = new Thickness(0, 40 - base3, 0, 0);

这篇关于对齐控件中文本的底部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆