对齐控件中文本的底部 [英] Align bottoms of text in controls
问题描述
以下片段:
<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
这是我编写的一种提取该值的方法.它使用反射来获取相关属性,因为它们对于任何单个基类都是不通用的(它们分别定义在 Control
、TextBlock
、Page
,TextElement
和其他的).
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屋!