Wpf 如何使用附加属性为指定关键字突出显示文本块中的粗体字

Wpf 如何使用附加属性为指定关键字突出显示文本块中的粗体字,wpf,xaml,Wpf,Xaml,目标是使用匹配的输入关键字加粗Textblock中文本的单词 例如:Stackoverflow是一个非常有用的工具,继续使用Stackoverflow来提高你的技能 当关键字为:Stackoverflow时,它现在应显示为 Stackoverflow是一个非常有用的工具,请继续使用Stackoverflow来提高您的技能 我试图使用附加属性来实现相同的目标。下面是相同的快照代码 public class HighLightKeyWord : DependencyObject { //T

目标是使用匹配的输入关键字加粗Textblock中文本的单词

例如:Stackoverflow是一个非常有用的工具,继续使用Stackoverflow来提高你的技能

当关键字为:Stackoverflow时,它现在应显示为

Stackoverflow是一个非常有用的工具,请继续使用Stackoverflow来提高您的技能

我试图使用附加属性来实现相同的目标。下面是相同的快照代码

public class HighLightKeyWord : DependencyObject
{

    //This word is used to specify the word to highlight
    public static readonly DependencyProperty BoldWordProperty = DependencyProperty.RegisterAttached("BoldWord", typeof(string), typeof(HighLightKeyWord),
        new PropertyMetadata(string.Empty, OnBindingTextChanged));

    public static string GetBoldWord(DependencyObject obj)
    {
        return (string)obj.GetValue(BoldWordProperty);
    }

    public static void SetBoldWord(DependencyObject obj, string value)
    {
        obj.SetValue(BoldWordProperty, value);
    }

    private static void OnBindingTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {

        var _Key = e.NewValue as string;
        var textblk = d as TextBlock;
        string SourceText = textblk.Text;
        SetBold(_Key, textblk, SourceText);

    }

    private static void SetBold(string key, TextBlock text, string SourceText)
    {
        text.Inlines.Clear();
        var words = SourceText.Split(' ');
        for (int i = 0; i < words.Length; i++)
        {
            var word = words[i];
            var inline = new Run() { Text = word + ' ' };
            if (String.Compare(word, key,  StringComparison.CurrentCultureIgnoreCase) == 0)
            {
                inline.FontWeight = FontWeights.Bold;
            }
            text.Inlines.Add(inline);
        }
    }

}
在Xaml中,我将值绑定为

<TextBlock Text="{Binding Path=Text}"  loc:HighLightKeyWord.BoldWord="{Binding Path=KeyWord}" />

上面的代码工作正常,但是当我通过数据绑定直接在xaml中设置HighlightText属性时,OnBindingTextChanged方法中文本块的Text属性变为空,并且在设置dependency属性时只调用一次该方法。 我使用这个基于拼写检查器概念的设计,以便其他团队成员可以在他们的项目中重用我的附加属性。
有人能建议如何解决这个问题吗?

无论您想修改TextBlock FontWeight属性还是其他显示属性,我都编写了以下静态方法,并发现它非常有用。(注意:该方法通过修改前台属性来突出显示文本。相同的原理可用于任何其他TextBlock显示属性。)

您可以使用TextBlock扩展语法调用此方法,如下所示:

TextBlockTitle.SetTextAndHighlightSubstring(_categoryItem.ItemText, _searchText);
在本例中,出现以下显示:


我最近遇到了同样的问题,文本绑定被破坏了。我意识到这是一个老问题,但我想我还是会分享我的发现

基本上,文本属性的数据绑定在内联线一刻就被切断了。我解决这个问题的方法是添加一个内部文本依赖属性,该属性复制了文本的绑定,因此后续的文本更改将继续触发高亮显示

在清除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);
      }
   }

   ...
}
在InternalTextProperty的propertyChangeCallback中,可以使用与OnBindingTextChanged()相同的代码,也可以将它们重构为另一个方法

对于那些不想自己编写代码的人。我创建了一个轻量级的nuget包,它向常规文本块添加高亮显示。您可以保留大部分代码不变,只需添加一些附加属性。默认情况下,该插件支持高亮显示,但您也可以在关键字上启用粗体、斜体和下划线

资料来源如下:

TextBlockTitle.SetTextAndHighlightSubstring(_categoryItem.ItemText, _searchText);
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);
      }
   }

   ...
}