You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:45:04