I’m working on a Silverlight project, where I wanted to enable my users to send private messages to each other, while enjoying the features of the RichTextBox. I also wanted to implement a search feature, so that my users could find their messages easily.
It turns out, that the only way, that I could easily get a serialized string out of the RichTextBox, was to use the RichTextBox.Xaml property. I created a test Silverlight project, and watched how the generated Xaml looked like:
As you can see, the generated Xaml code is very bloated. I intend to save all the private messages in a database, so that the database can perform search queries.
But saving the raw Xaml code wouldn’t be a very good solution, the entire messaging system would be taking much more space than was actually needed. So I came up with the idea to transform that Xaml code into the well known BB code, which is a very compact way of formatting text and is widely spread over the internet.
First I searched for existing solutions, with little success. Many solutions depend on third party RichTextBoxes, some of them aren’t free, and some other people have already created a one-way BBCode to Xaml Parser. But I needed a two-way conversion between BBCode and Xaml, which leads to the most beloved:
Do it yourself.
So while seeing how the RichTextBox generated Xaml, I quickly realized that it wouldn’t be an easy and clean job, because of several reasons:
- The standard way of encoding a newline (by pressing Return) is to create a new paragraph tag:
<Paragraph><Run>This is some</Run></Paragraph> <Paragraph><Run>multiline test.</Run></Paragraph>
- Each time a new format for the text started, the current run tag was closed and a new one was opened, with the entire formatting information, regardless of the previous format:
<Run FontWeight="Bold">This is some bold </Run> <Run FontWeight="Bold" FontStyle="Italic">and italic text</Run>
- Hyperlinks don’t support line breaks out of the box; pressing the Return key while having the caret inside of a hyperlink in the RichEditBox didn’t do anything.
So after thinking it over several times, I decided that if I really wanted to generate BB-Code as everyone knows it, I had to keep track of the open BB-Code tags, and if the text had a completely new format, I needed to close them in reverse order, just like in html, and open new tags. Since I was rolling up my own system, and my main goal was to create a compact, search friendly serialization of rich formatted text, I decided to disregard the context-sensitive nature of existing BB-code. Thus I developed a new way of serializing rich-formatted text, which is fully BB-Code compatible. I’ll call it eBB (e for easy). With eBB you can no longer think of the code as some sort of tag-tree, instead you must think of it as a state machine. When a eBB tag opens, it means that from that moment on in the text that state is active. When a tag closes, that state becomes inactive. This also implies that tags don’t have to be closed in the end.
What I also needed to change is the way that the RichTextBox interpreted the Return key press. I wanted it to genereate line breaks instead of new paragraphs. So I overloaded the KeyDown event of my RichTextBox:
private void rtbOriginal_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { rtbOriginal.Selection.Insert(new LineBreak()); e.Handled = true; } }
Converting Xaml to eBB is now a piece of cake: Each time a Run or Hyperlink tag opens, I compare the new format to the old format, and open or close an eBB tag whenever I need to. I currently only support these tags:
- [color=#FFFFFFFF]text[/color]
- [url=http://example.com]text[/url]
- [size=14]bigger text[/size]
- [b]bold[/b]
- [i]italic[/i]
- [u]underline[/u]
Suppose I wanted to encode this line of text, the eBB-code would look this way:
A line with rich-formatted text and link
A line [b]with rich-[i]formatted[/i] text [url=http://example.com]and[/b] link
Notice that I don’t necessarily need to close the url tag, and that I close the bold tag directly after having opened the url tag. This context-free syntax would be invalid in standard BB-code, but it serves my purpose. What’s implicitly great is that standard BB-Code is supported and will be parsed correctly.
Converting eBB back to Xaml is also very simple. Each time a tag opens or closes, I update a structure containing all formatting infos, and generate corresponding Run or Hyperlink Xaml tags with all needed formatting infos.
A demo application with complete source code for the converter class can be downloaded from this site: XamlBBConverter.zip
Frank,
I really like this. Thank you for this post. This could be of great help towards me in a project, and could end up getting enhanced and used. The project is a well-known and trafficked financial message board.
Regards,
– Eric