Không có giải pháp chỉ XAML, bạn phải sử dụng mã phía sau. Ngoài ra, ngay cả với mã-đằng sau, không có giải pháp chung cho điều này, bởi vì nếu văn bản của bạn là đa dòng? Đường cơ sở nào nên được sử dụng trong trường hợp đó? Hoặc nếu có nhiều yếu tố văn bản trong mẫu của bạn thì sao? Chẳng hạn như một tiêu đề và nội dung, hoặc nhiều hơn, mà đường cơ sở sau đó?
Tóm lại, đặt cược tốt nhất của bạn là căn chỉnh văn bản theo cách thủ công sử dụng lề trên cùng/dưới cùng.
Nếu bạn sẵn sàng đưa ra giả định rằng bạn có một phần tử văn bản, bạn có thể tìm ra khoảng cách pixel của đường cơ sở từ phía trên của phần tử bằng cách tạo đối tượng FormattedText
với tất cả các thuộc tính giống nhau của yếu tố văn bản. Đối tượng FormattedText
có thuộc tính double
Baseline
giữ giá trị đó. Lưu ý rằng bạn vẫn sẽ phải nhập thủ công một lề, bởi vì phần tử có thể không được đặt chính xác trên đầu hoặc cuối vùng chứa của nó.
Xem diễn đàn MSDN bài đăng này: Textbox Baseline
Dưới đây là một phương pháp tôi đã viết rằng chiết xuất giá trị đó. Nó sử dụng sự phản chiếu để nhận các thuộc tính có liên quan vì chúng không phổ biến với bất kỳ lớp cơ sở nào (chúng được định nghĩa riêng biệt trên Control
, TextBlock
, Page
, TextElement
và có thể là các loại khác).
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, để phản hồi nhận xét của bạn, tôi không tin bạn thực sự đã thử giải pháp này, vì nó hoạt động.Dưới đây là một ví dụ:
Dưới đây là các 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>
Và đây là mã đằng sau đó đạt được điều này
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);
ah haa! Bản cập nhật của bạn làm rõ vấn đề. –