【问题标题】:Best way to implement a Parsing/Editable Richtextbox in WPF在 WPF 中实现解析/可编辑 Richtextbox 的最佳方法
【发布时间】:2010-03-13 00:58:27
【问题描述】:

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

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

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

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

干杯

【问题讨论】:

    标签: wpf parsing input richtextbox


    【解决方案1】:

    如果您可以针对 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 个字符)并通过按索引组织块的树进行访问。原因是在一个巨大数组的开头插入一个字符非常昂贵。

    【讨论】:

    • 以上代码是否仍然适用于最新的 WPF RichTextBox?我之所以问,是因为我看到需要进行一些更改才能使代码正常工作,例如 startindex、endindex 无法正确读取文本更改值,需要重新计算..?
    • JP 我想你会发现这只是一个错误的例子。原理是合理的,但找出正确索引值的实际逻辑并不完全正确。
    【解决方案2】:

    CodeProject 上查看此内容。这是一篇您可能对通过子类化扩展的RichTextBox 控件感兴趣的文章...看看这篇文章 - 一个具有更多功能的Extended RichTextBox 控件

    【讨论】:

    • 这是我见过的最糟糕的答案之一。所有这三个链接都浪费了我的时间:所描述的 RTF 解析器远不如 WPF,另外两个链接指向与问题完全无关的过时 WinForms 内容。更糟糕的是,你必须下载代码才能发现它甚至不是 WPF!
    • @Ray:对不起,如果我浪费了你的时间,有可以解析 RTF 的 NRTFTTree Parser,我只是希望你能收集代码给你一个想法......
    猜你喜欢
    • 2021-10-22
    • 1970-01-01
    • 2011-04-28
    • 2012-03-14
    • 2011-06-11
    • 2010-09-20
    • 2013-05-29
    • 1970-01-01
    • 2010-11-16
    相关资源
    最近更新 更多