在 RichTextBox 中使用之前,将 XML 中的格式属性添加到文本

Add formatting attributes from XML to text prior to use in a RichTextBox

我的 XML 文件存储文本段落并具有定义段落类型的属性。

例如:

  <Content>
    <Paragraph Type="Period">
      <Text>A long long time ago</Text>
    </Paragraph>
    <Paragraph Type="location">
      <Text>in a galaxy far, far away</Text>
    </Paragraph>
    <Paragraph Type="GeneralText">
      <Text>It is a period of civil war. Rebel spaceships, striking from a hidden base, ... Pursued by the Empire’s sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy….</Text>
    </Paragraph>
    <Paragraph Type="location">
      <Text>And here's another location</Text>
    </Paragraph>
  </Content>

我正在寻找一种方法,当文本显示在 RichTextBox 中时向其添加某些属性。

例如,段落类型:

我知道如何遍历 XML 和如何检索 XML 属性以及如何将每个段落附加到 RichTextBox,但如何添加这些格式属性?

一些可以帮助您入门的建议。

▶ 使用 class 对象来保存您的 XML 描述符可能需要的所有属性

▶ 预先构建这些对象的列表,这些对象在首次构建应用程序时已知,可以选择在设计时和 运行 时编辑它们的属性,以进行自定义。

▶ 提供添加更多这些描述符的方法:

  • 动态 - 在加载 XML 文件时读取类型的 XML 属性
  • 交互式 - 使用 PropertyGrid 将元素添加到段落描述符集合中
  • 以编程方式 - 允许在 运行-Time 请求时使用自定义界面添加元素。

您还可以拥有保存新描述符对象的代码(序列化到光盘、添加到用户设置等)

在示例中,自定义控件 - 从 RichTextBox 派生 - 包含从已知模式加载 XML 数据所需的所有逻辑,分配段落类型描述符(使用 class 对象, XmlDescriptor,每读一段)。
使用此信息,将文本发送到 RichTextBox 容器,使用指定的参数格式化新的 Selection。

请注意,XmlDescriptor 对象的集合是通过 ParagraphsDescriptors 属性 公开的。可以使用 PropertyGrid 编辑此集合:您可以修改现有描述符或添加新描述符。
如果更改描述符集合,请重新加载 XML 以查看应用的更改。

使用自定义 RichTextBox LoadXml() 方法(传递一个 XML 字符串或重载该方法以同时传递文件路径)加载XML 并应用样式。

Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Xml.Linq

<DesignerCategory("Code")>
Public Class RichTextBoxEx
    Inherits RichTextBox

    Private m_xmlContent As String = String.Empty

    Public Sub New()
        Me.ParagraphsDescriptors = New List(Of XmlDescriptor)({
            New XmlDescriptor("Period", HorizontalAlignment.Left, Color.Red, Color.LightYellow, 10, 20),
            New XmlDescriptor("Location", HorizontalAlignment.Center, Color.Brown, Color.Orange, 5, 0),
            New XmlDescriptor("GeneralText", HorizontalAlignment.Left, Color.White, Color.Black, 0, 0)
        })
    End Sub

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>
    Public Property ParagraphsDescriptors As List(Of XmlDescriptor)

    Public ReadOnly Property XmlContent As String
        Get
            Return m_xmlContent
        End Get
    End Property

    Public Function LoadXml(xml As String, Optional append As Boolean = False) As Boolean
        If (String.IsNullOrEmpty(xml)) Then Return False
        Try
            Dim xElm As XElement = XElement.Parse(xml)
            m_xmlContent = xml
            If (Not append) Then Me.Clear()
            For Each node As XElement In xElm.Elements.Where(Function(n) n.Name.LocalName.Equals("Paragraph"))
                Dim txt = node.Elements.FirstOrDefault(Function(elm) elm.Name.LocalName.Equals("Text"))
                If txt IsNot Nothing Then
                    AddParagraph(node.Attributes, txt.Value)
                End If
            Next
            Return True
        Catch ex As Exception
            MessageBox.Show($"LoadXml failed: {ex.Message}")
            Return False
        End Try
    End Function

    Public Sub AddParagraph(attributes As IEnumerable(Of XAttribute), text As String)
        Dim paragraphType = attributes.FirstOrDefault(Function(a) a.Name.LocalName.Equals("Type"))?.Value
        If String.IsNullOrEmpty(paragraphType) Then Throw New ArgumentException("ParagraphType")

        ' Parse the other Attributes, eventually, to map them to XmlDescriptor properties 
        Dim descriptor = ParagraphsDescriptors.FirstOrDefault(Function(d) d.ParagraphType.Equals(paragraphType))
        If descriptor Is Nothing Then descriptor = New XmlDescriptor(paragraphType)

        Dim selStart = Me.TextLength
        Me.AppendText(text + ChrW(10))
        Me.Select(selStart, text.Length)
        Me.SelectionAlignment = descriptor.Alignment
        Me.SelectionIndent = descriptor.LeftIndent
        Me.SelectionRightIndent = descriptor.RightIndent
        Me.SelectionBackColor = descriptor.BackColor
        Me.SelectionColor = descriptor.ForeColor
    End Sub

    <TypeConverter(GetType(ExpandableObjectConverter))>
    Public Class XmlDescriptor
        Public Sub New()
        End Sub

        Public Sub New(parName As String)
            ParagraphType = parName
        End Sub

        Public Sub New(parName As String, textAlign As HorizontalAlignment, bkColor As Color, textColor As Color, indentLeft As Integer, indentRight As Integer)
            ParagraphType = parName
            Alignment = textAlign
            BackColor = bkColor
            ForeColor = textColor
            LeftIndent = indentLeft
            RightIndent = indentRight
        End Sub

        Public Property ParagraphType As String = String.Empty
        Public Property Alignment As HorizontalAlignment = HorizontalAlignment.Left
        Public Property BackColor As Color = SystemColors.Window
        Public Property ForeColor As Color = SystemColors.ControlText
        Public Property LeftIndent As Integer = 0
        Public Property RightIndent As Integer = 0
    End Class
End Class