4

Mon objectif est de créer un contrôle TextBlock personnalisé qui a une nouvelle propriété de dépendance, SearchText. Cette propriété contiendra une expression régulière. Toutes les occurrences de cette expression régulière dans le texte du TextBlock seront mises en évidence en utilisant un style personnalisé (un autre DP).Mettre en évidence Rechercher TextBlock

Ma mise en œuvre actuelle implique la suppression de tous les objets Inline dans InlineCollection du bloc de texte. Je remplis alors le TextBlock avec des exécutions pour le texte non surligné et exécute pour le texte surligné avec le style appliqué (cette méthode ne supporte pas l'addition de lignes directement au TextBlock, au lieu que TextBlock.TextProperty doit être utilisé).

Fonctionne très bien, mais parfois je reçois une exception étrange en essayant d'effacer les Inlines: InvalidOperationException: "Impossible de modifier les enfants logiques pour ce noeud à ce moment car une marche en arbre est en cours." Ce problème semble être lié à this un. Je modifie les inlines dans la fonction TextChanged, mais j'utilise un indicateur pour éviter les modifications récursives infinies.

Avez-vous des idées sur la façon d'architecturer ce contrôle personnalisé? Y a-t-il une meilleure manière de faire cela? Comment contourner cette exception?

Merci!

Répondre

2

Je ne sais toujours pas s'il existe une meilleure façon de le faire, mais il semble que j'ai trouvé du travail.

Je mettais à jour les inlines/runs dans une fonction qui était déclenchée par la notification de modification pour TextProperty et SearchTextProperty.

Maintenant, je déclenche le code de mise en surbrillance/mise à jour à partir d'un appel Dispatcher.BeginInvoke() dans la notification de modification avec DispatcherPriority.Normal.

1

Dans le cas où quelqu'un veut un exemple de la façon de procéder, je trouve this

+0

Il est recommandé de fournir un résumé de ce qui est dans le lien au cas où il serait cassé. –

5

Dans ma mise en œuvre, je résolu ce problème en ajoutant simplement une autre propriété de dépendance, appelée OriginalText. Une fois modifié, j'ai mis à jour la propriété Text et mis à jour la surbrillance. Voici le code:

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

C'est génial. Merci d'avoir posté votre solution. –

Questions connexes