C# WPF 如何实现TextBlock单行文本两端对齐
WPF 单行TextBlock两端对齐实现方案
WPF原生TextAlignment.Justify仅对包含换行的多行文本生效,单行文本因缺少行尾结束标记不会触发两端对齐排版逻辑,以下是两种符合要求的实现方案,无需硬编码空格,也不会修改原有字号:
方案1:自定义附加属性实现(推荐)
通过附加属性自动计算文本与控件可用宽度的差值,动态调整单词间距实现两端对齐,适配动态文本场景。
第一步:定义附加属性类
public static class TextBlockExtensions { public static readonly DependencyProperty JustifySingleLineProperty = DependencyProperty.RegisterAttached( "JustifySingleLine", typeof(bool), typeof(TextBlockExtensions), new PropertyMetadata(false, OnJustifySingleLineChanged)); public static void SetJustifySingleLine(DependencyObject element, bool value) { element.SetValue(JustifySingleLineProperty, value); } public static bool GetJustifySingleLine(DependencyObject element) { return (bool)element.GetValue(JustifySingleLineProperty); } private static void OnJustifySingleLineChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not TextBlock textBlock || !(bool)e.NewValue) return; textBlock.Loaded += (_, _) => AdjustSingleLineJustify(textBlock); textBlock.SizeChanged += (_, _) => AdjustSingleLineJustify(textBlock); } private static void AdjustSingleLineJustify(TextBlock textBlock) { if (string.IsNullOrEmpty(textBlock.Text) || textBlock.ActualWidth <= 0) return; // 计算原始文本宽度 var formattedText = new FormattedText( textBlock.Text, System.Globalization.CultureInfo.CurrentCulture, textBlock.FlowDirection, new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch), textBlock.FontSize, textBlock.Foreground, VisualTreeHelper.GetDpi(textBlock).PixelsPerDip); var textWidth = formattedText.Width; var totalSpacing = textBlock.ActualWidth - textWidth; if (totalSpacing <= 0) return; // 拆分单词分配额外间距 var words = textBlock.Text.Split(' '); if (words.Length <= 1) return; var extraSpacePerGap = totalSpacing / (words.Length - 1); textBlock.Inlines.Clear(); for (int i = 0; i < words.Length; i++) { textBlock.Inlines.Add(words[i]); if (i != words.Length - 1) { textBlock.Inlines.Add(new Run(" ") { CharacterSpacing = (int)(extraSpacePerGap * 1000 / textBlock.FontSize) }); } } } }
第二步:XAML中使用
首先在页面/窗口根节点声明自定义类的命名空间别名,示例:xmlns:local="clr-namespace:你的项目命名空间"
然后修改原有XAML代码:
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="First is quite lengthy" HorizontalAlignment="Stretch" local:TextBlockExtensions.JustifySingleLine="True"/> <TextBlock Text="This one's shorter" HorizontalAlignment="Stretch" local:TextBlockExtensions.JustifySingleLine="True"/> <TextBlock Text="This one too" HorizontalAlignment="Stretch" local:TextBlockExtensions.JustifySingleLine="True"/> <TextBlock Text="This one is a bit longer again" HorizontalAlignment="Stretch" local:TextBlockExtensions.JustifySingleLine="True"/> </StackPanel>
该方案中所有TextBlock的宽度会自动对齐到最长文本的宽度,无需手动设置固定值。
方案2:轻量原生方案(适合文本固定场景)
如果不想编写自定义逻辑,可以通过触发原生Justify规则实现,首先测量得到最长文本的实际宽度,将所有TextBlock的Width设置为该值,再添加如下属性即可:
<TextBlock Text="示例文本" Width="280" <!-- 替换为实际测量的最长文本宽度 --> TextAlignment="Justify" TextWrapping="Wrap" MaxHeight="16" <!-- 替换为你的TextBlock字号大小 --> LineHeight="16"/> <!-- 替换为你的TextBlock字号大小 -->
原理是通过TextWrapping="Wrap"让WPF识别到文本可换行,触发两端对齐逻辑,同时用MaxHeight限制高度避免文本真的折行。
内容的提问来源于stack exchange,提问作者nooblet2
相关产品推荐
相关产品推荐

