没有唯一的 XAML 解决方案,您必须使用后面的代码。此外,即使使用代码隐藏,也没有通用的解决方案,因为如果您的文本是多行的怎么办?在这种情况下应该使用哪个基线?或者如果您的模板中有多个文本元素怎么办?比如一个header和一个content,或者更多,那是哪个baseline呢?
简而言之,最好的办法是使用顶部/底部边距手动对齐文本。
如果您愿意假设您有一个文本元素,您可以通过实例化具有FormattedText
现有文本元素的所有相同属性的对象来计算基线到元素顶部的像素距离。该FormattedText
对象具有double
Baseline
保存该值的属性。请注意,您仍然必须手动输入边距,因为元素可能不会完全靠在其容器的顶部或底部。
请参阅此 MSDN 论坛帖子:文本框基线
这是我编写的提取该值的方法。它使用反射来获取相关属性,因为它们对任何单个基类都不通用(它们分别在Control
、TextBlock
、Page
和TextElement
其他类上定义)。
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,作为对您的评论的回应,我不相信您实际上已经尝试过这个解决方案,因为它有效。这是一个例子:
这是 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>
这是实现这一目标的代码
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);