How to highlight the word(s) with bold in text block for specified keyword using the attached property

后端 未结 2 1271
感动是毒
感动是毒 2021-01-23 07:46

The objective is to bold the word(s) of text in Textblock with matching input keyword.

For example: Stackoverflow is a very helpful, keep using Stackoverflow to sharpen

相关标签:
2条回答
  • 2021-01-23 08:40

    I recently ran into the same problem with the broken text binding. I realize this is an old question, but figured I'd share my finding anyway.

    Basically Text property's data-binding is severed the moment Inlines.Clear is called. The way I got around this problem was by adding an internal text dependency property that replicated text's binding so subsequent text changes would continue to trigger highlighting.

    Try adding something like this before clearing text.Inlines.

    protected static string GetInternalText(DependencyObject obj)
    {
        return (string)obj.GetValue(InternalTextProperty)
    }
    
    protected static void SetInternalText(DependencyObject obj, string value)
    {
        obj.SetValue(InternalTextProperty, value);
    }
    
    // Using a DependencyProperty as the backing store for InternalText.  This enables animation, styling, binding, etc...
    protected static readonly DependencyProperty InternalTextProperty =
            DependencyProperty.RegisterAttached("InternalText", typeof(string),
    typeof(HighlightableTextBlock), new PropertyMetadata(string.Empty, OnInternalTextChanged));
    
    private static void SetBold(string key, TextBlock text, string SourceText)
    {
       //Add the following code to replicate text binding
       if (textblock.GetBindingExpression(HighlightableTextBlock.InternalTextProperty) == null)
       {
          var textBinding = text.GetBindingExpression(TextBlock.TextProperty);
    
          if (textBinding != null)
          {
              text.SetBinding(HighLightKeyWord.InternalTextProperty, textBinding.ParentBindingBase);
          }
       }
    
       ...
    }
    

    In InternalTextProperty's propertyChangeCallback you can have the same code as OnBindingTextChanged() or you could refactor them into another method.

    For those who don't want to write their own code. I have created a lightweight nuget package that adds highlighting to regular TextBlock. You can leave most of your code intact and only have to add a few attached properties. By default the add-on supports highlighting, but you can also enable bold, italic and underline on the keyword.

    https://www.nuget.org/packages/HighlightableTextBlock/

    The source is here: https://github.com/kthsu/HighlightableTextBlock

    0 讨论(0)
  • 2021-01-23 08:41

    Whether you want to modify a TextBlock FontWeight attribute or another display property, I've written the following static method and found it very useful. (Note: The method illustrates highlighting text by modifying the Foreground property. The same principle can be used for any other TextBlock display attribute.)

        static Brush DefaultHighlight = new SolidColorBrush(Colors.Red);
    
        public static void SetTextAndHighlightSubstring(this TextBlock targetTextBlock, string sourceText, string subString, Brush highlight = null)
        {
            if (targetTextBlock == null || String.IsNullOrEmpty(sourceText) || String.IsNullOrEmpty(subString))
                return;
            targetTextBlock.Text = "";
            var subStringPosition = sourceText.ToUpper().IndexOf(subString);
            if (subStringPosition == -1)
            {
                targetTextBlock.Inlines.Add(new Run { Text = sourceText });
                return;
            }
            var subStringLength = subString.Length;
            var header = sourceText.Substring(0, subStringPosition);
            subString = sourceText.Substring(subStringPosition, subStringLength);
            var trailerLength = sourceText.Length - (subStringPosition + subStringLength);
            var trailer = sourceText.Substring(subStringPosition + subStringLength, trailerLength);
            targetTextBlock.Inlines.Add(new Run { Text = header });
            targetTextBlock.Inlines.Add(new Run { Text = subString, Foreground = highlight ?? DefaultHighlight });
            targetTextBlock.Inlines.Add(new Run { Text = trailer });
        }
    

    You can call this method using the TextBlock extension syntax like so:

    TextBlockTitle.SetTextAndHighlightSubstring(_categoryItem.ItemText, _searchText);
    

    In this example, the following display resulted:

    0 讨论(0)
提交回复
热议问题