示例程序:在TextBlock中,点击一个文字,其样式会改变,再一次点击后目标文字会还原原始样式。 诀窍就是使用TextBlock和RichTextBox类型的GetPositionFromPoint方法,point参数是在控件位置内的坐标,snapToText会自动根据位置来找到插入点(把他理解成类似光标的插入位置)。而当TextPointer返回后,TextPointer.LogicalDi
  

  示例程序:在TextBlock中,点击一个文字,其样式会改变,再一次点击后目标文字会还原原始样式。

  

image

 

  诀窍就是使用TextBlock和RichTextBox类型的GetPositionFromPoint方法,point参数是在控件位置内的坐标,snapToText会自动根据位置来找到插入点(把他理解成类似光标的插入位置)。而当TextPointer返回后,TextPointer.LogicalDirection会指向鼠标的位置,这个是非常非常重要的。这样的话,用过这个返回的TextPointer,我们可以得到位置所指向的文字!

  好,我们先设置好界面,XAML:

<TextBlock HorizontalAlignment="Center"

          VerticalAlignment="Center"

          Text="Mgen ABCDEFG HIGHLMN 一二三四五"

          MouseLeftButtonUp="TextBlock_MouseLeftButtonUp"

          FontSize="15"

          Name="tbl"/>

  我们可以在事件中(也就是TextBlock_MouseLeftButtonUp方法中)做一下测试:

  var point = e.GetPosition(tbl);

  //获取TextPointer

  var poz = tbl.GetPositionFromPoint(point, true);

  System.Diagnostics.Debug.WriteLine(poz.LogicalDirection);

  如果点击一个文字的左侧,那么LogicalDirection是Forward,如果是右侧,LogicalDirection则会使Backward。

  接下来就是获取文字和设置属性,使用TextPointer.GetNextInsertionPosition方法,参数则是获取的TextPointer.LogicalDirection属性,这样下一个TextPointer会指向文字的另一个方向。然后通过这两个TextPointer创建TextRange,通过GetPropertyValue和ApplyPropertyValue方法来获取TextRange的属性和设置属性,通过ClearAllProperties方法清空所有设置的属性,这样文字就又恢复原样了。

  完成代码:

private void TextBlock_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

{

    var point = e.GetPosition(tbl);

    //获取TextPointer

    var poz = tbl.GetPositionFromPoint(point, true);

 

    var nextPoz = poz.GetNextInsertionPosition(poz.LogicalDirection);

    if (nextPoz != null)

    {

        var range = new TextRange(poz, nextPoz);

 

        //设置TextRange属性

        var brush = range.GetPropertyValue(TextElement.ForegroundProperty);

        if (brush.Equals(Brushes.YellowGreen))

        {

            range.ClearAllProperties();

        }

        else

        {

            range.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.YellowGreen);

            range.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);

            range.ApplyPropertyValue(TextElement.FontSizeProperty, 30.0);

        }

    }

}
 

private void TextBlock_Loaded(object sender, RoutedEventArgs e)
        {
            try
            {
                List<TextRange> lstRange = FindAllMatchedTextRanges(sender as TextBlock, _FolderViewModel.FolderModel.SearchCOText);
               
                foreach (var i in lstRange)
                    i.ApplyPropertyValue(TextBlock.ForegroundProperty, "#4682B4");
            }
            catch (PresentationException pex)
            {
                pex.Report();
            }
            catch (Exception ex)
            {
                new PresentationException(ex).Report();
            }
        }

        private void TextBlock_Loaded_1(object sender, RoutedEventArgs e)
        {
            try
            {
                List<TextRange> lstRange = FindAllMatchedTextRanges(sender as TextBlock, _FolderViewModel.FolderModel.SearchCOText,true);

                foreach (var i in lstRange)
                    i.ApplyPropertyValue(TextBlock.ForegroundProperty, "#4682B4");
            }
            catch (PresentationException pex)
            {
                pex.Report();
            }
            catch (Exception ex)
            {
                new PresentationException(ex).Report();
            }
        }

 

private List<TextRange> FindAllMatchedTextRanges(TextPointer position, string key)
        {
            List<TextRange> trList = new List<TextRange>();
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    String text = position.GetTextInRun(LogicalDirection.Forward);
                    Regex regex = new Regex(key, RegexOptions.IgnoreCase);
                    MatchCollection mc = regex.Matches(text);
                    foreach (Match match in mc)
                    {
                        TextPointer start = position.GetPositionAtOffset(match.Index);
                        TextPointer end = start.GetPositionAtOffset(match.Value.Length);
                        trList.Add(new TextRange(start, end));
                    }
                }
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }
            return trList;
        }

        private List<TextRange> FindAllMatchedTextRanges(TextBlock control, string keyWord)
        {

            List<TextRange> trList = new List<TextRange>();
            List<TextRange> tLst = new List<TextRange>();
            List<string> matchedAndKeys = new List<string>();

            string[] orKeys,andKeys;

            orKeys= keyWord.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string orkey in orKeys)
            {
                andKeys = orkey.Split(new string[] { "&&" }, StringSplitOptions.RemoveEmptyEntries);
                matchedAndKeys.Clear();
                tLst.Clear();

                foreach (string andKey in andKeys)
                {
                    var ttLst = FindAllMatchedTextRanges(control.ContentStart, andKey);
                    if (ttLst.Count > 0)
                    {
                        tLst.AddRange(ttLst);
                        matchedAndKeys.Add(andKey);
                    }
                }
                if (matchedAndKeys.Count == andKeys.Length)
                    trList.AddRange(tLst);
            }

            return trList;
        }

        private List<TextRange> FindAllMatchedTextRanges(TextBlock control, string keyWord, bool isTags)
        {
            string[] tags = control.Text.Split("|".ToArray(), StringSplitOptions.RemoveEmptyEntries);
            control.Text = control.Text.Replace('|', ' ');
            string[] orKeys, andKeys;
            TextPointer position = control.ContentStart;
            List<TextRange> tagTextRangeList = new List<TextRange>();
            List<TextRange> trList = new List<TextRange>();
            List<TextRange> tLst = new List<TextRange>();
            List<string> matchedAndKeys = new List<string>();

            orKeys = keyWord.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            while (position != null)
            {
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
                {
                    String text = position.GetTextInRun(LogicalDirection.Forward);
                    foreach (string tag in tags)
                    {
                        Regex regex = new Regex(tag, RegexOptions.IgnoreCase);
                        Match match = regex.Match(text);
                        TextPointer start = position.GetPositionAtOffset(match.Index);
                        TextPointer end = start.GetPositionAtOffset(match.Value.Length);
                        tagTextRangeList.Add(new TextRange(start, end));
                    }
                    foreach (string orkey in orKeys)
                    {
                        andKeys = orkey.Split(new string[] { "&&" }, StringSplitOptions.RemoveEmptyEntries);
                        matchedAndKeys.Clear();
                        tLst.Clear();
                        foreach (TextRange tag in tagTextRangeList)
                        {
                            foreach (string andKey in andKeys)
                            {
                                var ttLst = FindAllMatchedTextRanges(tag.Start, andKey);

                                if (ttLst.Count > 0)
                                {
                                    tLst.AddRange(ttLst);
                                    matchedAndKeys.Add(andKey);
                                }
                            }
                            if (matchedAndKeys.Count == andKeys.Length)
                                trList.AddRange(tLst);
                        }
                    }

                }
                position = position.GetNextContextPosition(LogicalDirection.Forward);
            }
            return trList;
        }