Ответ 1
Нет решения XAML, вам нужно использовать код. Кроме того, даже с кодовым отставанием нет общего решения для этого, потому что, если ваш текст многострочный? Какую базовую линию следует использовать в этом случае? Или что, если в вашем шаблоне есть несколько текстовых элементов? Например, заголовок и контент, или более, какой исходный уровень?
Короче говоря, лучше всего выровнять текст вручную, используя верхние/нижние поля.
Если вы хотите сделать предположение, что у вас есть один текстовый элемент, вы можете определить расстояние между пикселями базовой линии от вершины элемента, создав экземпляр объекта 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;
}
EDIT: 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);