我的目标是创建一个具有新依赖项属性SearchText的自定义TextBlock控件。此属性将包含正则表达式。将使用自定义样式(另一个DP)突出显示TextBlock文本中所有出现的正则表达式。
我当前的实现涉及清除TextBlock的InlineCollection中的所有Inline对象。然后我使用未突出显示的文本运行TextBlock并运行应用了样式的突出显示文本(此方法不支持直接向TextBlock添加内联,而是必须使用TextBlock.TextProperty)。
效果很好,但有时我在尝试清除Inlines时遇到一个奇怪的异常:InvalidOperationException:“此时无法修改此节点的逻辑子节点,因为正在进行树步行。”
此问题似乎与this问题有关。我正在修改TextChanged函数中的内联,但我正在使用一个标志来避免无限递归编辑。
有关如何构建此自定义控件的任何想法?有一个更好的方法吗?我该如何解决这个例外?
谢谢!
答案 0 :(得分:5)
在我的实现中,我通过添加另一个名为OriginalText
的依赖项属性来解决这个问题。修改后,我更新了Text
属性并更新了突出显示。这是代码:
public class HighlightTextBlock : TextBlock
{
public string HighlightedText
{
get { return (string)GetValue(HighlightedTextProperty); }
set { SetValue(HighlightedTextProperty, value); }
}
public static readonly DependencyProperty HighlightedTextProperty =
DependencyProperty.Register("HighlightedText", typeof(string), typeof(HighlightTextBlock), new UIPropertyMetadata(string.Empty, UpdateHighlightEffect));
public static readonly DependencyProperty OriginalTextProperty = DependencyProperty.Register(
"OriginalText", typeof(string), typeof(HighlightTextBlock), new PropertyMetadata(default(string), OnOriginalTextChanged));
private static void OnOriginalTextChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
var block = ((HighlightTextBlock)obj);
block.Text = block.OriginalText;
block.UpdateHighlightEffect();
}
public string OriginalText
{
get { return (string)GetValue(OriginalTextProperty); }
set { SetValue(OriginalTextProperty, value); }
}
private static void UpdateHighlightEffect(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (!(string.IsNullOrEmpty(e.NewValue as string) && string.IsNullOrEmpty(e.OldValue as string)))
((HighlightTextBlock)sender).UpdateHighlightEffect();
}
private void UpdateHighlightEffect()
{
if (string.IsNullOrEmpty(HighlightedText)) return;
var allText = GetCompleteText();
Inlines.Clear();
var indexOfHighlightString = allText.IndexOf(HighlightedText, StringComparison.InvariantCultureIgnoreCase);
if (indexOfHighlightString < 0)
{
Inlines.Add(allText);
}
else
{
Inlines.Add(allText.Substring(0, indexOfHighlightString));
Inlines.Add(new Run()
{
Text = allText.Substring(indexOfHighlightString, HighlightedText.Length),
Background = Consts.SearchHighlightColor,
});
Inlines.Add(allText.Substring(indexOfHighlightString + HighlightedText.Length));
}
}
private string GetCompleteText()
{
var allText = Inlines.OfType<Run>().Aggregate(new StringBuilder(), (sb, run) => sb.Append(run.Text), sb => sb.ToString());
return allText;
}
}
答案 1 :(得分:2)
仍然不确定是否有更好的方法来完成这项工作,但我似乎找到了解决方法。
我正在更新由TextProperty和SearchTextProperty的更改通知触发的函数中的内联/运行。
现在我正在使用DispatcherPriority.Normal在更改通知中从Dispatcher.BeginInvoke()调用中触发突出显示/更新代码。
答案 2 :(得分:1)
如果有人想要一个如何做到这一点的例子,我找到了this