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

如何仅在动态尺寸TextBlock文本被截断时显示ToolTip?

仅在TextBlock文本截断时显示ToolTip的实现方案

这个需求在UWP开发里挺常见的,默认ToolTip不管文本有没有截断都会显示,确实不够友好。咱们可以通过自定义附加属性结合布局计算的方式,精准判断文本是否被截断,再动态控制ToolTip的显示状态,具体实现如下:

步骤1:创建附加属性辅助类

先写一个静态辅助类,给TextBlock添加“是否截断”的状态标记,并且自动监听布局变化更新这个状态:

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

public static class TextBlockHelper
{
    // 定义附加属性:标记文本是否被截断
    public static readonly DependencyProperty IsTextTruncatedProperty =
        DependencyProperty.RegisterAttached(
            "IsTextTruncated",
            typeof(bool),
            typeof(TextBlockHelper),
            new PropertyMetadata(false, OnIsTextTruncatedChanged));

    // 获取附加属性值的方法
    public static bool GetIsTextTruncated(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsTextTruncatedProperty);
    }

    // 设置附加属性值的方法
    public static void SetIsTextTruncated(DependencyObject obj, bool value)
    {
        obj.SetValue(IsTextTruncatedProperty, value);
    }

    // 属性变化回调:绑定/解绑SizeChanged事件
    private static void OnIsTextTruncatedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (d is TextBlock textBlock)
        {
            if ((bool)e.NewValue)
            {
                textBlock.SizeChanged += TextBlock_SizeChanged;
                UpdateTruncationState(textBlock); // 初始化时先判断一次
            }
            else
            {
                textBlock.SizeChanged -= TextBlock_SizeChanged;
            }
        }
    }

    // 布局变化时更新截断状态
    private static void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (sender is TextBlock textBlock)
        {
            UpdateTruncationState(textBlock);
        }
    }

    // 核心判断逻辑:文本是否被截断
    private static void UpdateTruncationState(TextBlock textBlock)
    {
        // 如果没开启文本截断,直接标记为未截断
        if (textBlock.TextTrimming == TextTrimming.None)
        {
            SetIsTextTruncated(textBlock, false);
            return;
        }

        // 计算文本完全显示需要的宽度
        textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
        double desiredWidth = textBlock.DesiredSize.Width;
        // 获取TextBlock实际分配的宽度
        double actualWidth = textBlock.ActualWidth;

        // 加个小阈值避免浮点数精度误差
        bool isTruncated = actualWidth < desiredWidth - 1e-3;
        SetIsTextTruncated(textBlock, isTruncated);
    }
}

步骤2:在XAML中配置使用

接下来修改你的TextBlock,通过绑定附加属性来控制ToolTip的启用状态:

首先在页面资源中添加布尔值转可见性的转换器(如果用ToolTipService.IsEnabled可以跳过这一步,直接用属性绑定):

<Page.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Page.Resources>

然后修改TextBlock的XAML代码:

<TextBlock x:Name="ContentHeader" 
           Text="{x:Bind Name}" 
           TextTrimming="CharacterEllipsis" 
           Tapped="ContentHeader_Tapped"
           <!-- 启用附加属性的截断监听 -->
           local:TextBlockHelper.IsTextTruncated="True"
           <!-- 绑定ToolTip内容 -->
           ToolTipService.ToolTip="{x:Bind ContentHeader.Text, Mode=OneWay}"
           <!-- 仅当文本截断时启用ToolTip -->
           ToolTipService.IsEnabled="{x:Bind local:TextBlockHelper.GetIsTextTruncated(ContentHeader), Mode=OneWay}"
           ToolTipService.Placement="Right"/>

原理说明

  • 附加属性IsTextTruncated设为True后,会自动监听TextBlock的SizeChanged事件,每次布局变化时重新计算截断状态。
  • 通过Measure方法获取文本完全显示所需的宽度,和TextBlock实际宽度对比,判断是否被截断。
  • 最后把ToolTip的IsEnabled绑定到这个截断状态,只有文本被截断时,ToolTip才会在鼠标hover时显示。

这个方案的优势是可以复用在多个TextBlock上,完全符合XAML的声明式风格,不需要写大量重复的后台代码。

内容的提问来源于stack exchange,提问作者Prithvi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:50:00