有些时候,我们会碰到在输入文本时高亮一些文本关键字,譬如以下这图:
很明显,这个输入的文本中有四个关键字,正常文本都是黑色,关键字文本用了其他颜色。那么我们如何达到这种效果呢。wpf的textblock控件有个TextEffects属性,专门获取或设置用于此元素中的文本内容的效果,因此,可以用textblock来显示输入的文本,从而达到高亮文本的效果,显示的问题解决了,那文本的输入,编辑呢?由于textblock只是显示文本的控件,无法输入,编辑,所以我们要换一个思路,用一些巧妙的方法达到这种可编辑的高亮文本效果。
1 <ScrollViewer x:Class="KeyWordTextBox.KWTextBox"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5 VerticalScrollBarVisibility="Auto"
6 >
7 <Grid>
8 <TextBlock LineHeight="1" x:Name="tbk" Text="{Binding ElementName=tbx,Path=Text}" Padding="4,3,0,0" TextWrapping="Wrap"></TextBlock>
9 <TextBox TextChanged="tbx_TextChanged" SizeChanged="tbx_SizeChanged" x:Name="tbx" AcceptsReturn="True" TextWrapping="Wrap" Background="Transparent" Foreground="#00000000" BorderBrush="#00000000"
10 ></TextBox>
11 </Grid>
12 </ScrollViewer>
在这里,我用了一个textbox和textblock控件分别用来文本编辑和文本显示,可以看到,这里是将textbox叠加到textblock上面,并且使得textbox透明,将textblock的Text绑定textbox的Text属性,从而使下面的textblock文本得以显示输入的文本。之后,我们只需要统一两个控件的文本位置,就能完成高亮文本的实现。
1 public List<Tuple<string, Brush>> Keys
2 {
3 get { return (List<Tuple<string, Brush>>)GetValue(KeysProperty); }
4 set { SetValue(KeysProperty, value); }
5 }
6
7 // Using a DependencyProperty as the backing store for Keys. This enables animation, styling, binding, etc...
8 public static readonly DependencyProperty KeysProperty =
9 DependencyProperty.Register("Keys", typeof(List<Tuple<string, Brush>>), typeof(KWTextBox), new PropertyMetadata(new List<Tuple<string, Brush>>()));
10
11
12 private void tbx_TextChanged(object sender, TextChangedEventArgs e)
13 {
14 tbk.Text = "";
15 tbk.TextEffects.Clear();
16 for (int i = 0; i < tbx.LineCount; i++)
17 {
18 string a = tbx.GetLineText(i);
19 if (a.Contains("\r\n"))
20 {
21 a = a.Substring(0, a.IndexOf("\r\n"));
22 }
23 if (i == 0)
24 {
25 tbk.Text += a;
26 }
27 else
28 {
29 tbk.Text += "\n" + a;
30 }
31 }
32 string s = this.tbk.Text;
33 int start = 0;
34 foreach (var key in Keys)
35 {
36 start = 0;
37 while (start < s.Length)
38 {
39 var i = s.IndexOf(key.Item1, start);
40 if (i != -1)
41 {
42 TextEffect tex = new TextEffect()
43 {
44 Foreground = key.Item2,
45 PositionCount = key.Item1.Length,
46 PositionStart = i,
47 };
48 this.tbk.TextEffects.Add(tex);
49 start = i + key.Item1.Length;
50 }
51 else
52 {
53 break;
54 }
55 }
56 }
57
58 }
59
60 private void tbx_SizeChanged(object sender, SizeChangedEventArgs e)
61 {
62 tbx_TextChanged(sender, null);
63 }
以上就是在输入文本时触发的事件,也就是TextChange事件,在这里先使得textblock对齐textbox,之后再遍历文本,查找关键字,改变textblock的TextEffects属性。至此,这个小功能就基本完成了。