如何给wp(Windows phone)中搜索关键字加亮?
问题来源
最近在群里看到群友讨论在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>
整个实现大概就是这样,最后截一张图给大家看看。
总结
问题总有解决的方法的,很多你看似是比较困难的事情,其实都是由最基础的知识去一步步分解出来解决的,所以善于思考,举一反三,才是快速解决问题的根本途径!
(有问题,大家多多交流,加群163259145,加群请记得说:博客园)
--业精于勤而荒于嬉,行成于思而毁于随--