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

UWP中RichTextBlock文本高亮保留格式的实现咨询

Solution: Preserve Formatting While Highlighting in UWP RichTextBlock

Your current approach loses formatting because you're splitting the original text and creating new Run elements from scratch, which don't carry over the original font styles, colors, etc. The correct way to handle this without modifying the original content is using TextHighlighter—it's designed specifically to highlight text ranges while preserving existing formatting.

Here's how to implement it step by step:

Step 1: Understand TextHighlighter Basics

TextHighlighter lets you define one or more TextRange objects (each representing a start index and length of text to highlight) and applies a brush to those ranges. It works directly with your existing content, so there's no need to split or rebuild your RichTextBlock's inlines.

Step 2: Implement the Highlighting Logic

Replace your existing btnFind_Click method with the following code. This will:

  • Collect all text and track each Run's position in the combined text
  • Find all occurrences of the search term
  • Map each occurrence back to the original text ranges
  • Apply the highlight using TextHighlighter
private void btnFind_Click(object sender, RoutedEventArgs e)
{
    string searchTerm = txbToFind.Text.Trim();
    if (string.IsNullOrEmpty(searchTerm))
    {
        // Clear existing highlights if search term is empty
        RichTextBlockText.TextHighlighters.Clear();
        return;
    }

    // Step 1: Collect all text and track each Run's start/end indices
    List<RunInfo> runInfos = new List<RunInfo>();
    int currentPosition = 0;
    foreach (Run run in Testo.Inlines.OfType<Run>())
    {
        int length = run.Text.Length;
        runInfos.Add(new RunInfo { Run = run, StartIndex = currentPosition, EndIndex = currentPosition + length });
        currentPosition += length;
    }

    string fullText = string.Concat(runInfos.Select(r => r.Run.Text));
    List<TextRange> highlightRanges = new List<TextRange>();

    // Step 2: Find all occurrences of the search term
    int searchIndex = fullText.IndexOf(searchTerm, StringComparison.OrdinalIgnoreCase);
    while (searchIndex != -1)
    {
        int termLength = searchTerm.Length;
        int termEndIndex = searchIndex + termLength;

        // Step 3: Map the occurrence to the relevant Runs and create TextRanges
        foreach (var runInfo in runInfos)
        {
            // Check if this Run overlaps with the current search term
            if (runInfo.EndIndex > searchIndex && runInfo.StartIndex < termEndIndex)
            {
                int rangeStart = Math.Max(searchIndex, runInfo.StartIndex) - runInfo.StartIndex;
                int rangeLength = Math.Min(termEndIndex, runInfo.EndIndex) - Math.Max(searchIndex, runInfo.StartIndex);

                highlightRanges.Add(new TextRange
                {
                    StartIndex = runInfo.StartIndex + rangeStart,
                    Length = rangeLength
                });
            }
        }

        // Find next occurrence
        searchIndex = fullText.IndexOf(searchTerm, searchIndex + termLength, StringComparison.OrdinalIgnoreCase);
    }

    // Step 4: Apply the highlights
    RichTextBlockText.TextHighlighters.Clear();
    if (highlightRanges.Any())
    {
        TextHighlighter highlighter = new TextHighlighter();
        highlighter.Background = new SolidColorBrush(Colors.Yellow);
        highlighter.Ranges.AddRange(highlightRanges);
        RichTextBlockText.TextHighlighters.Add(highlighter);
    }
}

// Helper class to track Run positions
private class RunInfo
{
    public Run Run { get; set; }
    public int StartIndex { get; set; }
    public int EndIndex { get; set; }
}

Step 3: Clean Up Old Code

You can delete the MakeHighlightedParagraph method entirely—TextHighlighter handles all highlight styling directly without needing to create new inline elements.

How This Works

  • Preserves Original Formatting: We never modify the original Run elements. The TextHighlighter simply overlays a background color on the specified text ranges, leaving original font styles, colors, and sizes intact.
  • Handles Cross-Run Highlights: If your search term spans multiple Run elements (e.g., part in the italic run and part in the bold run), the code correctly splits the highlight into relevant ranges across those Runs.
  • Flexible Search: The example uses case-insensitive search—you can change StringComparison.OrdinalIgnoreCase to Ordinal if you want case-sensitive matching.

Additional Notes

  • TextHighlighter supports advanced brush types like LinearGradientBrush if you want custom highlight styles.
  • To highlight multiple terms with different colors, create separate TextHighlighter objects (each with its own brush and ranges) and add all to the TextHighlighters collection.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:31:59