Victor's blog

Stay hungry, stay foolish.

0%

WPF中不同文字显示不同颜色(高亮)

本文代码来自于 Stackoverflow @Blechdose,感谢!
但由于代码不完全满足需求,所以稍改了一下,并未完整封装。

功能概述:

实现自动替换TextBlock内容中的多个占位符,并将替换后的字符高亮(样式自定义)。

用例:

1
2
3
4
5
6
7
8
9
10
<!--
若HighlightTermBehavior处于另外的类库中,则需额外添加此定义:
xmlns:MyControls="clr-namespace:MyControls;assembly=MyControls"

另:HighlightTermBehavior.Text和TermToBeHighlighted也可使用动态或静态资源绑定
-->
<TextBlock TextWrapping="Wrap" FontWeight="Bold" FontSize="14" Padding="10" TextAlignment="Center"
MyControls:HighlightTermBehavior.TermToBeHighlighted="PS|Options"
MyControls:HighlightTermBehavior.Text="Press {0} and {1}">
</TextBlock>

效果:

源码(HighlightTermBehavior):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
namespace MyControls
{
public static class HighlightTermBehavior
{
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached(
"Text",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));

public static string GetText(FrameworkElement frameworkElement) => (string)frameworkElement.GetValue(TextProperty);
public static void SetText(FrameworkElement frameworkElement, string value) => frameworkElement.SetValue(TextProperty, value);


public static readonly DependencyProperty TermToBeHighlightedProperty = DependencyProperty.RegisterAttached(
"TermToBeHighlighted",
typeof(string),
typeof(HighlightTermBehavior),
new FrameworkPropertyMetadata("", OnTextChanged));

public static string GetTermToBeHighlighted(FrameworkElement frameworkElement)
{
return (string)frameworkElement.GetValue(TermToBeHighlightedProperty);
}

public static void SetTermToBeHighlighted(FrameworkElement frameworkElement, string value)
{
frameworkElement.SetValue(TermToBeHighlightedProperty, value);
}


private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock textBlock)
SetTextBlockTextAndHighlightTerm(textBlock, GetText(textBlock), GetTermToBeHighlighted(textBlock));
}

private static void SetTextBlockTextAndHighlightTerm(TextBlock textBlock, string text, string termToBeHighlighted)
{
textBlock.Text = string.Empty;

if (string.IsNullOrEmpty(text))
return;
//此处使用“|”将需要高亮的字符串分割成参数数组,然后使用string.Format进行格式化,可自行调整
text = string.Format(text, termToBeHighlighted.Split('|'));

var textParts = SplitTextIntoTermAndNotTermParts(text, termToBeHighlighted);

foreach (var textPart in textParts)
AddPartToTextBlockAndHighlightIfNecessary(textBlock, termToBeHighlighted, textPart);
}

private static void AddPartToTextBlockAndHighlightIfNecessary(TextBlock textBlock, string termToBeHighlighted, string textPart)
{
if (termToBeHighlighted.Contains(textPart))
AddHighlightedPartToTextBlock(textBlock, textPart);
else
AddPartToTextBlock(textBlock, textPart);
}

private static void AddPartToTextBlock(TextBlock textBlock, string part)
{
//此处样式为硬编码,有待优化🤣
textBlock.Inlines.Add(new Run { Text = part, FontWeight = FontWeights.Bold, Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0)) });
}

private static void AddHighlightedPartToTextBlock(TextBlock textBlock, string part)
{
//此处样式为硬编码,有待优化🤣
textBlock.Inlines.Add(new Run { Text = part, FontWeight = FontWeights.Bold, Foreground = new SolidColorBrush(Color.FromRgb(0xFF, 0, 0)) });
}


public static List<string> SplitTextIntoTermAndNotTermParts(string text, string term)
{
if (string.IsNullOrEmpty(text))
return new List<string>() { string.Empty };

return Regex.Split(text, $@"({term})")
.Where(p => p != string.Empty)
.ToList();
}
}
}