Reputation: 39
My XML file stores paragraphs of text and has an attribute which defines what kind of paragraph it is.
For example :
<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>
I am looking for a way to add certain attributes to the text when it is shown in a RichTextBox.
For instance, paragraph of type:
Period
, the text should have a yellow forecolor, a red backcolor, an indention of 10
and a right indentation of 20
.GeneralText
, there should be no formatting at all.Location
, it could have different formatting as well, brown, orange, centered, whatever!I know how to loop through the XML and how to retrieve the XML attributes and how to append each paragraph to a RichTextBox, but how do I add these formatting attributes?
Upvotes: 0
Views: 321
Reputation: 32288
Some suggestions that may get you started.
▶ Use a class object to hold all the properties that your XML descriptors may require
▶ Pre-build a list of these objects that are known when the application is first built, with the option of editing their properties at both Design-Time and Run-Time, for customization purposes.
▶ Provide means to add more of these descriptors:
You could also have code that saves new descriptor objects (serialized to disc, added to User Settings etc.)
In the example, a Custom Control - derived from RichTextBox - contains all the logic required to load XML data from a known schema, assigns a Paragraph Type descriptor (using a class object, XmlDescriptor
, for each Paragraph read).
Using this information, sends text to the RichTextBox container, formatting the new Selection with the parameters specified.
Note that the collection of XmlDescriptor
objects is exposed through the ParagraphsDescriptors
property. This collection can be edited using the PropertyGrid: you can modify existing descriptors or add new ones.
If you change the collection of descriptors, reload the XML to see the changes applied.
Use the custom RichTextBox LoadXml()
method (passing an XML string or overload the method to also pass the path of a file) to load the XML and apply the styles.
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
Upvotes: 1