gpt4 book ai didi

wpf - 在 WPF 中实现解析/可编辑 Richtextbox 的最佳方法

转载 作者:行者123 更新时间:2023-12-04 13:45:29 25 4
gpt4 key购买 nike

我正在尝试实现(最初作为原型(prototype)),一个可以实时解析的富文本框控件,以对其应用某些格式选项。这是在 WPF 中完成的,所以我认为最好的方法是扩展现有的富文本框控件。

我遇到了一个问题,它没有很好地记录并且示例非常慢(我发现的示例在每次击键时都会解析整个文档)。

我目前决定采用的方法是创建一个自定义的内联元素,它可以保存格式标签和内容。因此,我只需要解析当前段落和该段落中的运行以格式化标签。

有没有更好的方法来实现这一目标?请注意,这不适用于基于代码/语法的文档(因此 AvalonEdit 不合适)。

干杯

最佳答案

如果您可以针对 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.Paragraphrange.End.Paragraph .

此外,在许多情况下,将文档中所有文本的副本与 FlowDocument 本身分开存储会很有帮助。然后,当您对该文档应用更改时,您可以随时更新格式,而无需重新阅读文档。请注意,文本不应存储在单个大数组中,而应被剪切成小块(可能大约 1000 个字符)并通过按索引组织 block 的树进行访问。原因是在一个巨大数组的开头插入一个字符非常昂贵。

关于wpf - 在 WPF 中实现解析/可编辑 Richtextbox 的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2436827/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com