SilverLight高亮显示文本
文笔不好,就长话短说,就是想实现这样的效果,比如在成都二环路南一段一号附一号凤舞九天网吧 ,搜索 二环路 九天网吧 然后结果中高亮显示。
<local:TextBlockHighLight TextSource="成都二环路南一段一号附一号凤舞九天网吧" SearchText="二环路 九天网吧 " FontSize="12" FontFamily="Comic Sans MS" Margin="10"/>
代码如下:
public partial class TextBlockHighLight : UserControl { public TextBlockHighLight() { InitializeComponent(); this.LayoutRoot.Children.Add(_txtBlock); } public string TextSource { get { return (string)GetValue(TextSourceProperty); } set { SetValue(TextSourceProperty, value); } } private TextBlock _txtBlock = new TextBlock() { TextWrapping = TextWrapping.Wrap }; // Using a DependencyProperty as the backing store for TextSource. This enables animation, styling, binding, etc... public static readonly DependencyProperty TextSourceProperty = DependencyProperty.Register("TextSource", typeof(string), typeof(TextBlockHighLight), new PropertyMetadata(string.Empty, (o, e) => { var _this = o as TextBlockHighLight; if (string.IsNullOrWhiteSpace(e.NewValue.ToString())) { _this._txtBlock.Text = string.Empty; } else { _this._txtBlock.Text = e.NewValue.ToString(); } })); public string SearchText { get { return (string)GetValue(SearchTextProperty); } set { SetValue(SearchTextProperty, value); } } // Using a DependencyProperty as the backing store for SearchText. This enables animation, styling, binding, etc... public static readonly DependencyProperty SearchTextProperty = DependencyProperty.Register("SearchText", typeof(string), typeof(TextBlockHighLight), new PropertyMetadata(string.Empty, (o, e) => { var _this = o as TextBlockHighLight; ///如果字符都不为空 if ((!string.IsNullOrWhiteSpace(e.NewValue.ToString())) && (!string.IsNullOrWhiteSpace(_this._txtBlock.Text))) { System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.Append("<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">"); sb.Append(" <TextBlock.Inlines>"); sb.Append("<Run>"); var strs = e.NewValue.ToString().Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries); if (strs.Length > 1) { ///移除相同的 比如二环路 二环 那么会移除二环 for (int i = 0; i < strs.Length; i++) { for (int j = i + 1; j < strs.Length; j++) { if (strs[j].Contains(strs[i])) { ///无效的就设为空字符串 strs[i] = string.Empty; break; } } } } ///去除空字符串 strs = strs.Where(c => !string.IsNullOrEmpty(c)).ToArray(); var tmpSB = new System.Text.StringBuilder(); foreach (var item in strs) { if (tmpSB.Length == 0) { ///设置要高亮显示的样式 ,这里是测试就写死了 tmpSB.Append(_this.TextSource.Replace(item, "</Run><Run Text=\"" + item + "\" Foreground=\"Red\" FontWeight=\"Bold\"></Run> <Run>")); } else { tmpSB.Replace(item, "</Run><Run Text=\"" + item + "\" Foreground=\"Red\" FontWeight=\"Bold\"></Run> <Run>"); } } sb.Append(tmpSB.ToString()); sb.Append("</Run>"); sb.Append("</TextBlock.Inlines>"); sb.Append("</TextBlock>"); var txt = System.Windows.Markup.XamlReader.Load(sb.ToString()) as TextBlock; List<Inline> inlines = new List<Inline>(); txt.Inlines.ToList().ForEach(c => inlines.Add(c)); txt.Inlines.Clear(); _this._txtBlock.Text = null; foreach (var item in inlines) { _this._txtBlock.Inlines.Add(item); } _this.UpdateLayout(); } else { _this._txtBlock.Inlines.Clear(); _this._txtBlock.Text = _this.TextSource; } })); }
有些BUG,如果先更新要搜索的字符串,再更新源字符串不会触发事件,但是在实际使用中也是在源字符串里面找要搜索的字符串。搜索字符串里面是加空格分隔的。应该有更好的算法,也可以用正则匹配就用像我代码里面用 XamlReader.Load() ,但是在最先实现中,由于本生自己正则不是好好,所以希望大家提出更好的算法。