4

我的目標是創建一個具有新的依賴項屬性SearchText的自定義TextBlock控件。該屬性將包含一個正則表達式。在TextBlock文本中出現的所有正則表達式將使用自定義樣式(另一個DP)高亮顯示。突出顯示搜索TextBlock

我當前的實現包括清除TextBlock的InlineCollection中的所有Inline對象。然後,我爲TextBlock填充帶有未着色文本的運行,並針對應用了樣式的突出顯示的文本運行(此方法不支持直接向TextBlock添加內聯,而是必須使用TextBlock.TextProperty)。

很好用,但有時在嘗試清除Inline時出現一個奇怪的異常:InvalidOperationException:「此時由於樹正在進行,無法修改此節點的邏輯子節點。

這個問題似乎與this之一有關。我正在修改TextChanged函數中的內聯,但我使用一個標誌來避免無限遞歸編輯。

有關如何構建此自定義控件的任何想法?有一個更好的方法嗎?我如何解決這個異常?

謝謝!

回答

2

仍然不確定是否有更好的方法來完成此操作,但我似乎找到了解決辦法。

我正在更新由TextProperty和SearchTextProperty的更改通知觸發的函數中的內聯函數/運行。

現在我使用DispatcherPriority.Normal從更改通知中的Dispatcher.BeginInvoke()調用中觸發高亮/更新代碼。

1

如果有人想的是如何做到這一點的例子,我發現this

+0

建議提供一個鏈接內容摘要,以防鏈接中斷。 – 2012-10-26 20:53:46

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; 
    } 
} 
+0

這太好了。感謝您發佈您的解決方案。 – 2015-06-26 12:53:09

相關問題