2010-02-02 10 views
3

Lors de la création d'un éditeur personnalisé avec RichTextBox, j'ai rencontré le problème de trouver du texte supprimé/inséré avec les informations fournies avec l'événement TextChanged.événement WPF RichTextBox TextChanged - comment trouver du texte supprimé ou inséré?

L'instance de TextChangedEventArgs a quelques données utiles, mais je suppose que cela ne couvre pas tous les besoins. Supposons un scénario dans lequel plusieurs paragraphes sont insérés, et en même temps, le texte sélectionné (qui a lui-même englobé plusieurs paragraphes) a été supprimé. Avec l'instance de TextChangedEventArgs, vous disposez d'une collection de modifications de texte, et chaque modification ne vous fournit que le nombre de symboles supprimés ou ajoutés et la position de celui-ci.

La seule solution que j'ai à l'esprit est de conserver une copie du document et d'appliquer la liste des modifications. Mais comme les instances de TextChange ne nous donnent que le nombre de symboles insérés/supprimés (et non les symboles), nous devons mettre un symbole spécial (par exemple, '?') Pour désigner des symboles inconnus pendant que nous transformons notre copie originale de document. Après avoir appliqué toutes les modifications à la copie originale du document, nous pouvons ensuite la comparer avec le document mis à jour de richtextbox et trouver les correspondances entre les symboles inconnus et les vrais. Et enfin, obtenez ce que nous voulons !!!

Quelqu'un a déjà essayé cela? J'ai besoin de vos suggestions sur l'ensemble de la stratégie, et ce que vous pensez de cette approche.

Cordialement

Répondre

4

Cela dépend principalement de votre utilisation des modifications de texte. Lorsque la séquence comprend à la fois des insertions et des suppressions, il est théoriquement impossible de connaître les détails de chaque insertion, car certains des symboles insérés peuvent avoir été supprimés par la suite. Par conséquent, vous devez choisir ce que vous voulez vraiment les résultats:

  • Pour certaines fins, vous devez connaître la séquence exacte des changements, même si certains des symboles insérés doit être laissé comme « ? ».
  • À d'autres fins, vous devez savoir exactement comment le nouveau texte diffère de l'ancien, mais pas la séquence exacte dans laquelle les modifications ont été apportées.

Je vais techniques pour atteindre chacun de ces résultats. J'ai utilisé les deux techniques dans le passé, donc je sais qu'elles sont efficaces.

Pour obtenir la séquence exacte

Ceci est plus approprié si vous implémentez une histoire ou d'annuler journal ou à la recherche d'actions spécifiques. Pour ces utilisations, le processus que vous décrivez est probablement le meilleur, avec un changement possible: Au lieu de "trouver les correspondances entre les symboles inconnus et les vrais", il suffit de lancer le balayage pour trouver le texte de chaque "puis lancez-le en arrière pour trouver le texte de chaque" Insert ".

En d'autres termes:

  1. Commencez avec le texte initial et le processus des changements dans l'ordre. Pour chaque insertion, insérez '?' symboles Pour chaque suppression, supprimez le nombre de symboles spécifié et enregistrez-les en tant que texte supprimé.

  2. Commencez avec le texte final et traitez les modifications dans l'ordre inverse. Pour chaque , supprimez, insérez '?' symboles Pour chaque insérer, supprimez le nombre de symboles spécifié et enregistrez-les en tant que texte inséré.

Lorsque cela est terminé, tous vos « Insérer » et « Supprimer » les entrées de changement aura le texte associé au meilleur de nos connaissances, et tout texte qui a été inséré et immédiatement supprimé sera "? symboles

Pour obtenir la différence

Ceci est plus approprié pour marquer la révision ou la comparaison de version. Pour ces utilisations, utilisez simplement les informations de changement de texte pour calculer un ensemble de plages entières dans lesquelles des modifications peuvent être trouvées, puis utilisez un algorithme diff standard pour trouver les changements réels. Cela tend à être très efficace dans le traitement des changements incrémentiels, mais vous donne toujours les meilleures mises à jour. Ceci est particulièrement agréable lorsque vous collez un paragraphe de remplacement presque identique à l'original: l'utilisation des informations de changement de texte indiquera que tout le paragraphe est nouveau, mais en utilisant diff (c'est-à-dire cette technique) les courses qui sont réellement différentes.

Le code pour le calcul de la plage de modification est simple: Représentez la modification en quatre entiers (oldstart, oldend, newstart, newend). Courir à travers chaque changement:

  1. Si changeStart est avant newstart, réduire newstart à changeStart et réduire oldstart un montant égal
  2. Si changeEnd est après newend, augmenter newend à changeEnd et augmenter oldend un montant égal

Une fois cela fait, extraire la plage [oldstart, oldend] de l'ancien document et la plage [newstart, newend] du nouveau document, puis utiliser l'algorithme diff standard pour les comparer.

+0

Où par "algorithme de diff standard", je suppose que nous pouvons utiliser [quelque chose comme le "google-diff-match-patch" .NET lib] (http://code.google.com/p/google-diff- match-patch /) - trouvé à partir de [cette question] (http://stackoverflow.com/questions/138331/any-decent-text-diff-merge-engine-for-net). – ruffin