c# - 如何使用现有内容格式化 RichTextBox

标签 c# wpf formatting richtextbox

我从返回文本和格式信息的网络 API 获取数据。格式数据仅包括格式类型(粗体、斜体等)和该格式的范围。这样做的主要问题是,两个范围可能会“冲突”(例如,单词的前 3 个字符是粗体和斜体,但后 3 个字符只是斜体)。响应示例

{
  "text" : "This is an example text",
  "inlineStyles" : [
    {
      "offsetFromStart" : 5,
      "length" : 10,
      "type" : "bold"
    }
    {
      "offsetFromStart" : 10,
      "length" : 10,
      "type" : "italic"
    }
  ]
}

我已经尝试使用简单的 TextBlock 来执行此操作但失败了。我也用 RichTextBox 尝试过,但是当我添加 Span 时,我无法将它插入到原来的位置。我还坚持使用自己的跨度或运行来格式化每个字符,但这会非常难看,而且通常只是一个糟糕的解决方案。 (我主要关心的是速度..)

var tb = new RichTextBox();
var para = new Paragraph();
para.Inlines.Add("This is an example text") // Text parsed from the response

var startingPointer1 = para.ContentStart.GetPositionAtOffset(5);
var sp1 = new Span(startingPointer1, startingPointer1.GetPositionAtOffset(10));
sp1.FontWeight = FontWeights.Bold;

var startingPointer2 = para.ContentStart.GetPositionAtOffset(10);
var sp2 = new Span(startingPointer2 , startingPointer2 .GetPositionAtOffset(10));
sp2.FontStyle= FontStyles.Italic;

para.Inlines.Add(sp1);
para.Inlines.Add(sp2);
tb.Document.Blocks.Add(para);

此代码将其附加到末尾,当组合多个内联元素时(如我的示例),它根本不起作用(因为第一个问题。)

示例结果:example image

最佳答案

我认为您不能像这样重叠 Runs/Spans,您必须找到文本中的所有断点并分别设置每个文本范围的格式。它类似于 HTML,其中

<bold>some<italic> bold italic</bold> and other </italic> text.

无效。在你的情况下,你将有一个来自 (5,10) 的粗体,来自 (11, 15) 等的粗体。

找到某种 Range 可能很有用具有组合范围、拆分、查找重叠等方法的类。不久前我开始使用 this .

编辑:我完全不知道如何实现这一切(上次我做类似的事情差不多是 10 年前),但你可以尝试这样的事情:

  1. 创建 List<Range<int>> .最初它包含一个范围(0,文本长度)。
  2. 加载第一个样式,创建一个具有开始/结束偏移量的新范围。将此范围与列表中的范围重叠(或采用任何合适的方法)。这应该给你 3 个范围,比如 (0, start of style), (start of style, end of style), (end of style, end of text) .从列表中删除旧范围并添加新范围。
  3. 加载下一个,找到重叠部分,与列表中的范围,删除重叠的范围并添加新范围。
  4. 这应该会为您提供一个不重叠范围的列表。
  5. 现在,关于样式。您可以创建一种样式表类。这个类可以使用 FontWeights, FontStyles和其他枚举,在 System.Windows 中定义.修改列表,使其包含,例如,List<Tuple<int, Stylesheet>> .要计算重叠,只需使用元组中的第一个参数。
  6. 在从列表中删除旧范围之前,合并样式。
  7. 这应该会为您提供具有适当样式的非重叠区域列表。创建TextRange s,应用样式

其他可行的想法:

  1. 再次创建样式表。最初应该是正常重量、正常样式、默认字体大小等。
  2. 找到输入的下一个偏移量(第一个大于当前的偏移量),创建一个 TextRange并应用样式。
  3. 找到输入的下一个偏移量,修改当前(且唯​​一)的样式并应用。

如果我没记错的话,在文本中插入样式定义也算作字符,因此在最终文本中插入样式标签时可能需要调整偏移量。另外,我相信只使用 TextBlock 是可行的.

正如我所说,我不知道这是否像描述的那样工作,但这可能会给你和想法。

关于c# - 如何使用现有内容格式化 RichTextBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56977585/

相关文章:

c# - 使用fxcop申请sonarqube自定义规则我错过了什么?

没有目标类型的WPF样式?

c# - ADO.NET 实体数据模型 BUG

visual-studio-2010 - 我可以让 Visual Studio 将花括号与 if 语句(在 HTML 中)放在同一行吗?

python - 以欧洲格式显示 pandas 数据框

eclipse - 禁用 Eclipse 中的所有代码格式

c# - ASP.NET MVC HTML 转义

c# - IIS应用程序池过程使用大量内存

.net - WPF GridSplitter 使用 MinWidth 调整大小

c# - Log4net 一个 FileAppender 元素,以编程方式记录到多个文件