Не существует единственного решения XAML, вы должны использовать код позади. Кроме того, даже с выделенным кодом, для этого нет общего решения, потому что, если ваш текст многострочный? Какую базовую линию следует использовать в этом случае? Или что, если в вашем шаблоне несколько текстовых элементов? Таких как заголовок и контент, или больше, какой базовый уровень тогда?
Короче говоря, лучше всего выровнять текст вручную, используя верхние / нижние поля.
Если вы хотите сделать предположение, что у вас есть один текстовый элемент, вы можете определить расстояние в пикселях базовой линии от вершины элемента, создав экземпляр объекта FormattedText
со всеми теми же свойствами объекта. существующий текстовый элемент. Объект FormattedText
имеет свойство double
Baseline
, которое содержит это значение. Обратите внимание, что вам все равно придется вручную вводить поле, поскольку элемент может не располагаться точно в верхней или нижней части своего контейнера.
См. Это сообщение на форуме MSDN: Текстовое поле 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;
}
РЕДАКТИРОВАТЬ: Шимми, в ответ на ваш комментарий, я не думаю, что вы на самом деле пробовали это решение, потому что оно работает. Вот пример:
Вот 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);