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

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

问题描述

以下代码段:

<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唯一的解决方案,您必须在后面使用代码.另外,即使有代码隐藏,也没有通用的解决方案,因为如果您的文本是多行怎么办?在那种情况下应该使用哪个基线?或如果模板中有多个文本元素怎么办?例如标题和内容,或者更多,那么哪个基线呢?

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天全站免登陆