没有仅使用XAML的解决方案,您必须使用代码后台。即使使用代码后台,也没有通用解决方案,因为如果您的文本是多行的,会怎样?在这种情况下应该使用哪个基线?或者如果您的模板中有多个文本元素呢?例如标题和内容等,那么应该使用哪个基线呢?
简而言之,最好的方法是使用上/下边距手动对齐文本。
如果您愿意做出这样的假设,即您只有一个文本元素,那么您可以通过使用与现有文本元素完全相同的属性实例化FormattedText
对象来找出基线距离元素顶部的像素距离。 FormattedText
对象具有一个double
Baseline
属性,其中包含该值。注意,您仍然需要手动输入边距,因为元素可能无法完全靠近其容器的顶部或底部。
请参阅此MSDN论坛帖子:Textbox Baseline
以下是我编写的提取该值的方法。它使用反射获取相关属性,因为它们不属于任何单个基类(它们分别在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);