问题来源
最近在群里看到群友讨论在wp中有个搜索功能,要求搜索关键字在搜索结果内容中加亮(即加颜色),由于wp中没有自带这样的控件,于是大家各抒自见,有人说用第三方控件,有人说用richtextbox,也有人说用textblock和run!那究竟哪种实现比较好呢?个人看法,当然是用textblock和run实现起来是最方便的!
实现要求
1、给出关键字(如:我,购物,菜鸟,技术),关键字可以一个或者多个,多个用英文逗号隔开
2、能在搜索结果中对关键字进行加亮
3、能自定义加亮的颜色
4、要求复用性高
实现思路
如果要实现上面三点需求,首先我们想到是使用用户控件实现起来最好了,第一,二,三点分别用一个依赖属性表示,而第四点,既然是用户控件,作为一个控件,当然复用性强!
所以使用用户控件是再适合不过了!
材料准备
首先当然是在vs中新建一个wp的项目,然后添加一个用户控件的页面,这个估计不用我多说了,大家都会的了!在这里我新增一个HighlightControl的用户控件页面,在界面上添加一个TextBlock,命名为tbResult,打开codebehind,分别添加三个依赖属性,分别是TextProperty(搜索结果),HighlightWordProperty(关键字),HighlightWordColorProperty(加亮颜色),然后添加对应的包装属性,再添加回调方法!这些应该不用详解吧,学过wpf或者silverlight对这些应该很了解了!如果不懂可以评论问问!
下面贴出用户控件codebehind相应代码
1 public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(HighlightControl), new PropertyMetadata(new PropertyChangedCallback(HighlightControl.OnTextChanged)));
2 public static readonly DependencyProperty HighlightWordProperty = DependencyProperty.Register("HighlightWord", typeof(string), typeof(HighlightControl), new PropertyMetadata(new PropertyChangedCallback(HighlightControl.OnHighlightWordChanged)));
3 public static readonly DependencyProperty HighlightWordColorProperty = DependencyProperty.Register("HighlightWordColor", typeof(SolidColorBrush), typeof(HighlightControl), new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 0, 155, 227)), new PropertyChangedCallback(HighlightControl.OnHighlightWordColorChanged)));
4
5 public string Text
6 {
7 get
8 {
9 return (string)base.GetValue(HighlightControl.TextProperty);
10 }
11 set
12 {
13 base.SetValue(HighlightControl.TextProperty, value);
14 }
15 }
16
17 public SolidColorBrush HighlightWordColor
18 {
19 get
20 {
21 return (SolidColorBrush)base.GetValue(HighlightControl.HighlightWordColorProperty);
22 }
23 set
24 {
25 base.SetValue(HighlightControl.HighlightWordColorProperty, value);
26 }
27 }
28
29 public string HighlightWord
30 {
31 get
32 {
33 return (string)base.GetValue(HighlightControl.HighlightWordProperty);
34 }
35 set
36 {
37 base.SetValue(HighlightControl.HighlightWordProperty, value);
38 }
39 }
40
41
42 private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
43 {
44 HighlightControl control = d as HighlightControl;
45 if (e.NewValue == e.OldValue)
46 {
47 return;
48 }
49 HighlightControl.UpdateHighlight(control);
50 }
51
52 private static void OnHighlightWordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
53 {
54 HighlightControl control = d as HighlightControl;
55 HighlightControl.UpdateHighlight(control);
56 }
57
58 private static void OnHighlightWordColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
59 {
60 HighlightControl control = d as HighlightControl;
61 HighlightControl.UpdateHighlight(control);
62 }
63
64
65
66
67
68 private static void UpdateHighlight(HighlightControl control)
69 {
70 if (control == null)
71 {
72 return;
73 }
74 TextBlock textBlock = control.tbResult;
75 if (textBlock.Inlines.Count() > 0)
76 {
77 textBlock.Inlines.Clear();
78 }
79 //如果高亮为空,直接显示
80 if (string.IsNullOrEmpty(control.HighlightWord))
81 {
82 Run run = new Run();
83 run.Text = control.Text;
84 textBlock.Inlines.Add(run);
85 return;
86 }
87 string text = control.Text;
88 if (string.IsNullOrEmpty(text))
89 {
90 return;
91 }
92 TextBlock tempTextBlock = new TextBlock();//中间变量,方便run交换
93 string[] hightwordArray = control.HighlightWord.Split(',');
94 List<Run> listHightRun = new List<Run>();//添加已经加亮的run,方便判断
95 for (int i = 0; i < hightwordArray.Length; i++)
96 {
97 if (hightwordArray[i] == "") continue;//这个是放在关键字中有"",导致死循环
98
99 if (i == 0)
100 {
101 for (int num = text.IndexOf(hightwordArray[i], 0); num != -1; num = text.IndexOf(hightwordArray[i], 0))
102 {
103 // MessageBox.Show(num.ToString());
104 if (num != 0)
105 {
106 Run run2 = new Run();
107 run2.Text = text.Substring(0, num);
108 // textBlock.Inlines.Add(run2);
109 tempTextBlock.Inlines.Add(run2);
110
111 }
112 Run run3 = new Run();
113 run3.Text = text.Substring(num, hightwordArray[i].Length);
114 run3.Foreground = control.HighlightWordColor;
115 listHightRun.Add(run3);
116 //textBlock.Inlines.Add(run3);
117 tempTextBlock.Inlines.Add(run3);
118 text = text.Substring(num + hightwordArray[i].Length);
119 // MessageBox.Show(text);
120 }
121 if (!string.IsNullOrEmpty(text))
122 {
123 Run run4 = new Run();
124 run4.Text = text;
125 tempTextBlock.Inlines.Add(run4);//剩下没有被加亮的文字,加到一个run
126 }
127
128 }
129 else
130 {
131 // text = control.Text;
132 // MessageBox.Show("要遍历textBlock长度:" + textBlock.Inlines.Count.ToString());
133 for (int j = 0; j < textBlock.Inlines.Count; j++)
134 {
135 if (listHightRun.Any(h => h.Equals((textBlock.Inlines[j] as Run))))//如果是一个加亮的run,那就不需要遍历了
136 {
137 // MessageBox.Show("jin" + (textBlock.Inlines[j] as Run).Text);
138 Run runExist = (textBlock.Inlines[j] as Run);
139 textBlock.Inlines.Remove(textBlock.Inlines[j]);
140 tempTextBlock.Inlines.Add(runExist);
141 j--;
142 // MessageBox.Show("移除元素后textBlock长度:" + textBlock.Inlines.Count + " j: " + j);
143 continue;
144 }
145 string tempStr = (textBlock.Inlines[j] as Run).Text;
146 for (int num = tempStr.IndexOf(hightwordArray[i], 0); num != -1; num = tempStr.IndexOf(hightwordArray[i], 0))
147 {
148 //MessageBox.Show("要遍历的字符串:"+tempStr);
149 //MessageBox.Show("关键字是否存在:"+num.ToString());
150 //MessageBox.Show("关键字:"+hightwordArray[i]);
151 if (num != 0)
152 {
153 Run run2 = new Run();
154 run2.Text = tempStr.Substring(0, num);
155
156 tempTextBlock.Inlines.Add(run2);
157 }
158 Run run3 = new Run();
159 run3.Text = tempStr.Substring(num, hightwordArray[i].Length);
160 run3.Foreground = control.HighlightWordColor;
161 listHightRun.Add(run3);
162 tempTextBlock.Inlines.Add(run3);
163 tempStr = tempStr.Substring(num + hightwordArray[i].Length);
164 // (textBlock.Inlines[j] as Run).Text = (textBlock.Inlines[j] as Run).Text.Substring(num + hightwordArray[i].Length);
165 }
166 if (!string.IsNullOrEmpty(tempStr))//剩下没有被加亮的文字,加到一个run
167 {
168 Run run4 = new Run();
169 run4.Text = tempStr;
170 tempTextBlock.Inlines.Add(run4);
171 }
172 }
173 }
174 textBlock.Inlines.Clear();
175
176 int k = 0;
177 while (k < tempTextBlock.Inlines.Count)
178 {
179 Run tempRun = tempTextBlock.Inlines[k] as Run;
180 tempTextBlock.Inlines.Remove(tempTextBlock.Inlines[k]);
181 textBlock.Inlines.Add(tempRun);
182 k = 0;
183
184 }
185
186 //tempTextBlock.Inlines.Clear();
187
188 }
189
190
191
192 }
测试页面代码
1 <!--LayoutRoot 是包含所有页面内容的根网格-->
2 <Grid x:Name="LayoutRoot" Background="Transparent">
3 <Grid.RowDefinitions>
4 <RowDefinition Height="Auto"/>
5 <RowDefinition Height="*"/>
6 </Grid.RowDefinitions>
7
8
9
10 <!--TitlePanel 包含应用程序的名称和页标题-->
11 <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
12 <TextBlock Text="我的应用程序" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
13 <TextBlock Text="页面名称" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
14 </StackPanel>
15
16 <!--ContentPanel - 在此处放置其他内容-->
17 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
18
19 <control:HighlightControl Text="这是一个显示加亮在搜索结果中的关键字的用户控件" HighlightWord="高,的,这是,测试,亮,段" HighlightWordColor="Red">
20
21 </control:HighlightControl>
22
23 </Grid>
24
25
26 </Grid>
整个实现大概就是这样,最后截一张图给大家看看。
总结
问题总有解决的方法的,很多你看似是比较困难的事情,其实都是由最基础的知识去一步步分解出来解决的,所以善于思考,举一反三,才是快速解决问题的根本途径!