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() ,但是在最先实现中,由于本生自己正则不是好好,所以希望大家提出更好的算法。

原文地址:https://www.cnblogs.com/fat_li/p/3224968.html