Si vous pouvez cibler NET Framework 3.5 et supérieur, vous n'avez pas besoin de scanner le document à chaque modification: Abonnez-vous à l'événement TextChanged et utilisez la propriété TextChangedEventArgs.Changes pour obtenir la liste des modifications. Chaque fois que vous recevez un événement TextChanged, parcourez la collection Changes et créez une TextRange à partir de Offset, AddedLength et RemovedLength. Ensuite, développez cette TextRange pour recalculer la mise en forme, puis effectuez le calcul de la mise en forme et effectuez une mise à jour en tant qu'étape séparée (dans un rappel Dispatcher.BeginInvoke) afin de ne pas avoir d'événements TextChanged récursifs.
richTextBox.TextChanged += (obj, e)
{
var document = richTextBox.Document;
var length = document.ContentStart.GetOffsetToPosition(document.ContentEnd);
int totalAdd = 0;
int totalRemove = 0;
foreach(var change in e.Changes)
{
var expandBy = Math.Max(totalAdd,totalRemove);
var startIndex = change.Offset - expandBy;
var endIndex = changed.Offset + expandBy + Math.Max(totalAdd, totalRemove);
startIndex = Math.Max(startIndex, 0);
endIndex = Math.Min(endIndex, length);
var startPointer = document.ContentStart.GetPositionAtOffset(startIndex);
var endPointer = startPointer.GetPositionAtOffset(endIndex - startIndex);
var range = new TextRange(startPointer, endPointer);
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
DoParsingAndFormatting(ExpandRangeToUnitOfParsing(range));
});
totalAdd += change.AddedLength;
totalRemove += change.RemovedLength;
}
};
Si vous voulez trouver le paragraphe où un changement commence ou se termine, vous pouvez utiliser range.Start.Paragraph
et range.End.Paragraph
.
De même, pour de nombreuses situations, il sera utile de stocker une copie de tout le texte du document séparément du FlowDocument lui-même. Ensuite, lorsque vous appliquez des modifications à ce document, vous pouvez mettre à jour le formatage au fur et à mesure sans avoir à relire le document. Notez que le texte ne doit pas être stocké dans un seul grand tableau, mais plutôt découpé en petits morceaux (peut-être autour de 1000 caractères) et accessible via un arbre qui organise les pièces par index. La raison en est que l'insertion d'un personnage au début d'un énorme tableau est très coûteuse.
Est-ce que ce code s'applique encore pour la dernière version de RichTextBox? Je demande parce que je vois quelques changements nécessaires pour faire fonctionner le code correctement, comme startindex, endindex ne lit pas le texte a changé les valeurs correctement, besoin d'un recalcul ..? –
JP Je pense que vous trouverez que c'est juste un cas de bugs. Le principe est solide, mais la logique actuelle pour déterminer les bonnes valeurs d'index n'est pas tout à fait juste. – donovan