WPF类Windows11搜索文件关键字高亮色块实现

WPF的TextBlock推荐高亮无非就是变几个字的颜色(没错就是这样),用TextBlock + Run实现

<TextBlock>
    <!-- 普通文本 -->
    <Run Text="这是一段需要部分"/>

    <!-- 高亮文本 -->
    <Run Text="高亮显示" Foreground="Red" FontWeight="Bold"/>

    <!-- 继续普通文本 -->
    <Run Text="的示例文本"/>
</TextBlock>

但是在一些业务环境中,这种方式不被用户接受

1.文字花花绿绿,可能有视觉疲劳

2.不高大上,UI显示不符合当下潮流

这时候,目光 就情不自禁的放到了Windows上

虽然Win11经常被诟病,但是UI样式还是很前卫的

2b4b36a6da0f4d34ae186146b067e1fc

在网上找了一圈,没有合适的实现,现在就分享一下自己写的破东西

<Rectangle Margin="{Binding HighlightLeftMargin,UpdateSourceTrigger=PropertyChanged}" 
           Width="{Binding HighlightWidth,UpdateSourceTrigger=PropertyChanged}" 
           Height="42" Fill="Yellow" VerticalAlignment="Center" HorizontalAlignment="Left"
           RadiusX="12" RadiusY="12"/>

<TextBlock Foreground="Black" Text="The quick brown fox jumps over the lazy dog." 
           TextAlignment="Center" Loaded="TextBlock_Loaded" MaxWidth="520" FontSize="32"/>

XAML这样就有一个雏形了,核心思想就是在TextBlock下面放一个色块,动态调整色块来完成高亮

后台绑定数据:

private string _highlightword;
/// <summary>
/// 文件高亮词
/// </summary>
public string Highlightword
{
    get
    {
        return _highlightword;
    }
    set
    {
        _highlightword = value;
        RaisePropertyChanged();
    }
}

private Thickness _highlightLeftMargin;
/// <summary>
/// 文件高亮词距离左边距离
/// </summary>
public Thickness HighlightLeftMargin
{
    get
    {
        return _highlightLeftMargin;
    }
        set
    {
        _highlightLeftMargin = value;
        RaisePropertyChanged();
    }
}

private double _highlightWidth;
/// <summary>
/// 文件高亮词宽度
/// </summary>
public double HighlightWidth
{
    get
    {
        return _highlightWidth;
    }
    set
    {
        _highlightWidth = value;
        RaisePropertyChanged();
    }
}

这样基础就来搭好了,只需要小小计算一下就可以了

首先在文本加载完成的时候加入Loaded事件:

private void TextBlock_Loaded(object sender, RoutedEventArgs e)
{
    TextBlock textBlock = (TextBlock)sender;

    var fileDataContext = textBlock.DataContext as 你自己储存的数据类型;

    SetHighlightLocation(textBlock, 你自己储存的数据类型.Highlightword);
}

然后核心的方法就是这个 SetHighlightLocation 方法:

/// <summary>
/// 设置文本高光位置
/// </summary>
/// <param name="textBlock">文本控件</param>
/// <param name="keyword">关键词</param>
/// <returns></returns>
private void SetHighlightLocation(TextBlock textBlock, string keyword)
{
    string fullText = textBlock.Text;
    //没有关键词就别走下面了,渲染浪费性能
    if (String.IsNullOrEmpty(keyword)) return;

    //获得关键词在文本中的位置
    int index = fullText.IndexOf(keyword, StringComparison.Ordinal);
    if (index == -1) return;

    // 创建临时TextBlock测量高亮块距离左边像素宽度
    var tempTextBlock = new TextBlock
    {
        Text = fullText[..index],
        FontFamily = textBlock.FontFamily,
        FontSize = textBlock.FontSize,
        FontWeight = textBlock.FontWeight,
        FontStyle = textBlock.FontStyle
    };

    // 创建临时TextBlock测量高亮块宽度
    var tempTextBlock2 = new TextBlock
    {
        //这个就是Idex加上关键字的长度,就是高亮色块最右边位置
        Text = fullText[..(index + keyword.Length)],
        FontFamily = textBlock.FontFamily,
        FontSize = textBlock.FontSize,
        FontWeight = textBlock.FontWeight,
        FontStyle = textBlock.FontStyle
    };

    //确保两个临时文本块都被计算和渲染
    tempTextBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    tempTextBlock.Arrange(new Rect(tempTextBlock.DesiredSize));
    tempTextBlock2.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    tempTextBlock2.Arrange(new Rect(tempTextBlock2.DesiredSize));

    //用高亮块距离左边像素宽度长度(tempTextBlock.ActualWidth)+最大控件长度减去文本宽度的一半(即左右两边的空白像素宽度)
    var thickness = new Thickness((int)tempTextBlock.ActualWidth + ((textBlock.ActualWidth - textBlock.DesiredSize.Width) / 2), 0, 0, 0);
    //色块最右边位置减掉最左边位置就是色块长度
    var width = tempTextBlock2.ActualWidth - tempTextBlock.ActualWidth;

    ((你自己储存的数据类型)(textBlock.DataContext)).HighlightLeftMargin = thickness;
    ((你自己储存的数据类型)(textBlock.DataContext)).HighlightWidth = width;

*这里的 ((textBlock.MaxWidth - textBlock.ActualWidth) / 2) 主要为了处理文本是居中显示,那么没有到达最大文本宽度之前,左右都会有空白,不一定需要

这里用本机文件下的音乐测试,KeyWord为.mp3:
636bcb4998fd4ee7a07fca99173962c8

效果拔群!

posted @ 2026-08-10 11:09  Poetindusk  阅读(1)  评论(0)    收藏  举报