文筆很差,就長話短說,就是想實現這樣的效果,好比在成都二環路南一段一號附一號鳳舞九天網吧 ,搜索 二環路 九天網吧 而後結果中高亮顯示。算法
<local:TextBlockHighLight TextSource="成都二環路南一段一號附一號鳳舞九天網吧" SearchText="二環路 九天網吧 " FontSize="12" FontFamily="Comic Sans MS" Margin="10"/>
代碼以下:app
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() ,可是在最早實現中,因爲本生本身正則不是好好,因此但願你們提出更好的算法。測試