in Silverlight

Silverlight 2 (beta1) – Rich Text Viewer

By: Christoph Husse

This is a guest post by Christoph Husse. I would like to say “thank you” for writing great article and being a guest blogger in my blog. I’m pretty busy with my project this week and can’t write any post for a while. Thank you! Chris

Thanks,
Michael Sync

Download ~

Silverlight 2 (beta1) - Rich Text Viewer

Contents

  1. Introduction
    1. How to format text?
    1. How to change text formatting?
    1. How to use the component?
  2. A formatting Toolbar

Introduction

This article describes how to utilize my RichTextBlock component to display text with basic formatting and MSN smilies. In general the TextBlock provided by Microsoft isn’t useful in many cases. Its text wrapping option doesn’t work correctly and it only supports one text format per time. Please note that my one isn’t a RichTextEditor but only a kind of viewer! Like my Demo shows, you may apply the text written to any TextBox directly within a RichTextBlock which will lead into a kind of real-time preview. This should be enough until Silverlight will itself bring a RichTextEdit into play.
Of course the smilies got transparent borders which make them capable to be rendered over any given background without losing their smoothness.

1.1. How to format text?

The control uses a syntax free markup language (ML) to realize formatting. This has two advantages. One the one hand it’s very easy to understand and on the other hand it is not possible to type something invalid. These two facts make the control ready to be used by the general public. For example a reduced HTML is much harder to understand for anyone not involved in web development and, of course, much harder to parse. The provided formatting should be enough for nearly all common input purposes like messages, guest-books, forums, and so on…

Internally, all context rendering is done within an exception handler. If anything goes wrong, the box will just be empty instead of throwing an exception. This is to prevent you from some Denial of Service attacks. Imagine an attacker who types in text that throws such an exception and you have forgotten to catch it…

The ML supports the following text formatting:

The sample screenshot above has been rendered with the following ML text (AutoReturn = false):


<20>Big :@ <i>text <12>.

<item>
This is a simple item and should be visible among two lines... Or maybe three, who knows that yet ;)?
</item>

This is not an item.

<indent>
A non closed <br> indent showing that my small markup language is syntax free...

<item>
<arial><18><i>"We're just starting <b>a new item without </> <i>closing the previous one...
<item>
<blue>and <12>the whole <green>thing again!"</>
</item>

After this it is enough to close the items one time...<br>
The following shows all supported smilies:<br>

(W):-**-):-O|-)+o(:-#^o):((F)8-):D8-|8o|(L)(K):P:):$:|:'((H):S(U):@

1.2. How to change text formatting?

Of course, it is possible to change all the formatting macros. Internally a translation table with the following entry format is being used:

new RepEntry()
{
Rep = TextReplacements.Confused,
Text = new String[] {":S", ":-S", "*confused*", "*verwirrt*"}
},

The String-Array contains a list of macros that will be replaced by the given TextReplacement if encountered in text. All of those entries assemble the RichTextBlock.RepList. By changing the String-Array you may customize the markup language. The internal semantic is not changeable in any efficient manner. If you want the ML to behave in another way, you will have to rewrite appropriate code sections.

1.3. How to use the component?

The controls will always have a fixed width and a height-range. The reason for this is that there is simply no application in my mind that requires a width-range and it makes rendering much easier. The height will be adjusted every time the content is being updated and will never exceed its boundaries. Also no “half” lines will be displayed, like it is common with the normal TextBlock. If the last visible line does not fully fit into the component it is just skipped completely. Currently there are no ellipses supported if the text does not fit entirely into the visible control part.

The following is the same code as my Demo is using and will allow real-time preview of typed ML including a state block showing the current formatting at cursor position:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Demo
{
public partial class Page : UserControl
{
RichTextBox TextBox;
TextBlock State;
RichTextBlock TextBlock;

public Page()
{
InitializeComponent();

TextBox = new RichTextBox();

TextBox.Text = “Enter your text here :-)!”;

TextBox.Margin = new Thickness(100, 100, 0, 0);
TextBox.Width = 300;
TextBox.Height = 200;
TextBox.HorizontalAlignment = HorizontalAlignment.Left;
TextBox.VerticalAlignment = VerticalAlignment.Top;
TextBox.OnStateChanged += new StateChangedHandler(TextBox_OnStateChanged);

TextBlock = RichTextBlock.Create(TextBox.Text, 100, 320, 300, 0, 400);
TextBlock.HorizontalAlignment = HorizontalAlignment.Left;
TextBlock.VerticalAlignment = VerticalAlignment.Top;

TextBox.Preview = TextBlock;

State = new TextBlock();
State.Margin = new Thickness(100, 20, 0, 0);
State.Width = 300;
State.Height = 50;
State.HorizontalAlignment = HorizontalAlignment.Left;
State.VerticalAlignment = VerticalAlignment.Top;

LayoutRoot.Children.Add(State);
LayoutRoot.Children.Add(TextBox);
LayoutRoot.Children.Add(TextBlock);
}

void TextBox_OnStateChanged(object InSender, TextReplacements InState, bool IsValid)
{
State.Text = TextBox.StateToString();
}
}
}

If you are using huge contents for RichTextBlock or planning to frequently update the Text-Property, you might consider setting “RichTextBlock.AutoUpdate” to “false”, which will disable automatic re-rendering each time the Text-Property is changed. You manually have to call “Update()” if you want to re-render the content in this case!

As formatting heavily depends on special chars, don’t forget that Silverlight does currently only support US-keyboards. If you are using a non-US keyboard consider utilizing my InternationalTextBox instead of the TextBox provided by Microsoft!

2. A formatting Toolbar

If you plan to use a formatting toolbar to provide a more convenient user interface, you will need to determine the format settings at a given cursor position. This is to show the current formatting within the toolbar and of course to insert a proper command. For this reason I wrote a little TextBox extension supporting all of this stuff. I called it RichTextBox, even if this might be misleading but I had no clue how to name it more precisely. The following properties are exported:

A toolbar should register the “RichTextBox.OnStateChanged” event, to be notified each time the state at current cursor position has changed, maybe due to cursor movement or text updates. The handlers “IsValid” parameter will be set to “true” if “RichTextBox.SelectionLength” is zero, “false” otherwise. The reason for this is that it is rather complicated to support such formatting changes for custom text selections. And as far as it is not necessary, I’ve just skipped the feature. So if “IsValid” is “false” you should just disable all formatting components, except the smilies, which are still supported! Changing any of the above states when “IsValid” is “false” will have no effect…

To change the state at current cursor position, just set the above properties to any desired value. The RichTextBox will automatically insert a proper command into the text depending on current formatting.

To insert smilies at cursor position, just call RichTextBox.InsertSmiley().

If you want to realize a real-time preview you may also set the “RichTextBox.Preview” property to any RichTextBlock. It will be updated automatically.

And of course the RichTextBox automatically refers to your custom macro definition table. So you may change all macro definitions without losing the capabilities of this component…

Leave a Reply

12 Comments

  1. Hi Mike and Chris,

    Where should we use this code? Can you tell me some scenarios where we should use this code?

    I have checked your demo. It seems intesting (because I thought it’s Rich Text Editor for Silverlight) but it doesn’t have all functionalites of Rich Text Editor. Is it the early version of Rich Text Editor? OR Do you have any plan to create the Rich Text Editor for Silverlight?

  2. Hi tinz,

    Where should we use this code? Can you tell me some scenarios where we should use this code?

    I think it might be useful if you are creating in Silverlight-enabled chatting software… Silverlight 2 supports Socket so that it’s good to create some chatting clients with Silverlight. I think Chris will add more inputs for that.

    Is it the early version of Rich Text Editor? OR Do you have any plan to create the Rich Text Editor for Silverlight?

    This is what I’m thinking a lot these days. but I think we should probably wait Silverlight 2 beta 2… Chris told me that Rich Text Editor will be included in next release.

  3. I think there are many scenarios to use this code…

    As I said you may use it for any user input like chatting, messaging, forums, guestbooks and also for user profiles… Maybe also for text formatting within your website.

    If you miss any formatting you may easily add it by extending the macro definitions and adding proper handling code to the “TextBuilder” class…

    I need this component very frequently within my webservice so I thought it would be useful for others too…

  4. And as I pointed out within my article… There is no need for a rich text editor because microsoft will provide its own in the next releases… I think it will also be able to output and input XAML and HTML.

    My component focuses on something other… If you are chatting for example, you have no time to select formatting from a toolbar. This is why you need a simple formatting language that allows you to make your message looking more personalized. The same for messaging and all other user input. In many cases it’s just not possible to provide a format toolbar for any user input. And you will definitely need them for a real rich text editor!!

    As I am developing a webservice focused on chatting, messaging and personalized user profiles, this component is really important to me…

    regards chris

  5. Yes,Im looking forward for the new text editor to the microsoft ,The exsits one is just like a toy ,hope they can realse it as possiable as they can.

  6. don’t worry… next week we will provide a well featured RichTextEdit. Of course the job could be done better with native operation system utilities, as available to Microsoft, but as we don’t know when it ships…

    regards
    chris

  7. It would with some minor fixes…
    But first take a look at my RichTextEditor (www.codeplex.com/richtextedit) which is capable of all the things as well, Silverlight Beta 2 compatible and nearly the same if you use it in readonly mode…

    But if you really need this component, I will review the code.

    regards
    chris

  8. Hi this is exactly what we wanted. But it doesnt work with Silverlight 2. It will be great if we get the updated version with SL2 ASAP.

    Thanks.

  9. I need this control to wpf.
    How i can convert this control to wpf destop aplication?

  10. I think about the reason you titled this particular blog, “Silverlight 2 (beta1)
    – Rich Text Viewer”. In any case I actually enjoyed it!
    Thanks a lot-Monique