WPF RichTextBox TextChanged事件 - 如何查找已删除或插入的文本?

时间:2010-02-02 19:10:26

标签: wpf editor richtextbox undo-redo

在使用RichTextBox创建自定义编辑器时,我遇到了使用TextChanged事件提供的已删除/插入文本的问题。

TextChangedEventArgs的实例有一些有用的数据,但我想它并不能满足所有需求。假设插入了多个段落的场景,同时删除了所选文本(本身跨越多个段落)。

使用TextChangedEventArgs的实例,您有一组文本更改,每个更改仅为您提供已删除或添加的符号的数量及其位置。

我想到的唯一解决方案是保留文档副本,并在其上应用给定的更改列表。但由于TextChange的实例只给出了插入/删除符号(而不是符号)的数量,所以我们需要在我们转换原始副本时使用一些特殊符号(例如,'?')来表示未知符号。文档。

将所有更改应用于原始文档副本后,我们可以将其与richtextbox的更新文档进行比较,并找到未知符号与实际符号之间的映射。最后,得到我们想要的东西!!!

以前有人试过这个吗?我需要你对整个战略的建议,以及你对这种方法的看法。

此致

1 个答案:

答案 0 :(得分:4)

它主要取决于您对文本更改的使用。当序列包括插入和删除时,理论上不可能知道每个插入的细节,因为插入的一些符号可能随后被删除。因此,您必须选择您真正想要的结果:

  • 出于某些目的,您必须知道更改的确切序列,即使某些插入的符号必须保留为“?”。
  • 出于其他目的,您必须确切知道新文本与旧文本的不同之处,而不是更改的确切顺序。

我将采用技术来实现这些结果。我过去曾使用过这两种技术,所以我知道它们是有效的。

获取确切序列

如果您要实施历史记录或撤消日志或搜索特定操作,则更合适。

对于这些用途,您描述的过程可能是最好的,只有一个可能的变化:不要“找到未知符号和真实符号之间的映射”,只需向前运行扫描以查找每个“删除”的文本。然后向后运行以查找每个“插入”的文本。

换句话说:

  1. 从初始文本开始,按顺序处理更改。对于每个插入,插入'?'符号。对于每次删除,删除指定数量的符号并将其记录为删除的文本。

  2. 从最终文本开始,按相反顺序处理更改。对于每个 delete ,插入“?”符号。对于每个插入,删除指定数量的符号并将其记录为插入的文本。

  3. 完成后,所有“插入”和“删除”更改条目都将根据我们的知识获得相关文本,并且插入并立即删除的任何文本都将为“?”符号。

    获得差异

    这更适合修订标记或版本比较。

    对于这些用途,只需使用文本更改信息计算可以找到更改的一组整数范围,然后使用标准差异算法查找实际更改。这在处理增量更改方面往往非常有效,但仍然可以为您提供最佳更新。

    当您粘贴与原始文本几乎相同的替换段落时,这一点特别好:使用文本更改信息将指示整个段落是新的,但使用diff(即此技术)将仅标记那些符号运行实际上是不同的。

    计算更改范围的代码很简单:将更改表示为四个整数(oldstart,oldend,newstart,newend)。贯穿每个变化:

    1. 如果changestart在newstart之前,则将newstart减少为changestart并将oldstart减少等量
    2. 如果changeend在newend之后,则将newend增加到changeend并增加oldend等量
    3. 完成后,从旧文档中提取范围[oldstart,oldend],从新文档中提取[newstart,newend]范围,然后使用标准差异算法进行比较。