如果您可以以.NET Framework 3.5及更高版本爲目標,需要在每次更改時掃描文檔:只需訂閱TextChanged事件並使用TextChangedEventArgs.Changes屬性獲取更改列表。
每當您收到一個TextChanged事件時,迭代Changes集合並從Offset,AddedLength和RemovedLength構造一個TextRange。然後展開適當的TextRange以重新計算格式,然後執行格式化計算並將其更新爲獨立步驟(在Dispatcher.BeginInvoke回調中),以便最終不會產生遞歸TextChanged事件。
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;
}
};
如果你想找到的段落,其中一個變化的開始或結束,您可以使用range.Start.Paragraph
和range.End.Paragraph
。
此外,對於許多情況,將獨立於FlowDocument本身的所有文本的副本存儲在文檔中將會有所幫助。然後,當您對該文檔應用更改時,您可以隨時更新格式,而無需重新閱讀文檔。請注意,文本不應該存儲在一個大型數組中,而應剪成小塊(可能大約1000個字符),並通過按索引組織這些塊的樹來訪問。原因是在巨大數組的開頭插入一個字符非常昂貴。
上面的代碼仍然適用於最新的WPF RichTextBox?我在問,因爲我看到一些必要的變化,使代碼正常工作,如startindex,endindex沒有正確讀取文本更改值,需要重新計算..? – 2013-07-29 22:52:29
JP我想你會發現它只是一個錯誤的情況。原則是合理的,但找出合適的指標值的實際邏輯並不完全正確。 – donovan 2013-12-16 03:34:04