Rich Text Editor

Create a simple Rich Text Editor using RichTextArea with Open and Save plus Formatting such as Bold, Italics and Underline using Silverlight.

www.cespage.com/silverlight/sl4tut14.html

Step 1

Start Microsoft Visual Web Developer 2010 Express, then Select File then New Project... Select "Visual Basic" then "Silverlight Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

New Silverlight Application window should appear, uncheck the box "Host the Silverlight Application in a new Web site" and then select the required Silverlight Version, see below:

New Silverlight Application

Step 3

A Blank Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 4

Select Project then Add Reference... The "Add Reference" window should appear, select "System.XML.Linq" from the ".NET" List, see below:

Add System.XML.Linq Reference

Step 5

Add the Reference to "System.XML.Linq" by Clicking on OK.
Then from the All Silverlight Controls section in the Toolbox select the Canvas control:

Canvas Control

Step 6

Draw a Canvas on the Page then in the XAML Pane above the "</Grid>" then change the "Canvas1" line to the following:

<Canvas Height="95" Width="400" VerticalAlignment="Top" HorizontalAlignment="Left" Name="Toolbar"></Canvas>

See below:

MainPage with Toolbar Canvas

Step 7

Then from the Common Silverlight Controls section in the Toolbox select the Button control:

Button Control

Step 8

Draw Eight Buttons on the Canvas by dragging the Buttons from the Toolbox onto the Canvas then in the XAML Pane inbetween the "<Canvas>" and "</Canvas>" tags change the "<Button>" lines to the following:

<Button Canvas.Left="6" Canvas.Top="6" Height="23" Width="75" Name="New" Content="New"/> 
<Button Canvas.Left="87" Canvas.Top="6" Height="23" Width="75" Name="Open" Content="Open..."/> 
<Button Canvas.Left="168" Canvas.Top="6" Height="23" Width="75" Name="Save" Content="Save..."/> 
<Button Canvas.Left="249" Canvas.Top="6" Height="23" Width="75" Name="Print" Content="Print..."/>
<Button Canvas.Left="6" Canvas.Top="35" Height="23" Width="75" Name="Bold" Content="Bold"/> 
<Button Canvas.Left="87" Canvas.Top="35" Height="23" Width="75" Name="Italic" Content="Italic"/> 
<Button Canvas.Left="168" Canvas.Top="35" Height="23" Width="75" Name="Underline" Content="Underline"/> 
<Button Canvas.Left="249" Canvas.Top="35" Height="23" Width="75" Name="TimeDate" Content="Time Date"/>  

See below:

MainPage with Canvas and Buttons

Step 9

While still in the XAML Pane, below the last "<Button>" tag and above the "</Canvas>" type the following ComboBox XAML:

<ComboBox Canvas.Left="6" Canvas.Top="64" Height="23" Width="156" Name="Font" 
    FontFamily="{Binding SelectedItem.FontFamily, RelativeSource={RelativeSource Self}}" 
    FontSize="{Binding SelectedItem.FontSize, RelativeSource={RelativeSource Self}}">
  <ComboBoxItem Content="Arial" Tag="Arial" FontFamily="Arial" FontSize="12" IsSelected="True"/>
  <ComboBoxItem Content="Arial Black" Tag="Arial Black" FontFamily="Arial Black" FontSize="12"/>
  <ComboBoxItem Content="Comic Sans MS" Tag="Comic Sans MS" FontFamily="Comic Sans MS" FontSize="12"/>
  <ComboBoxItem Content="Courier New" Tag="Courier New" FontFamily="Courier New" FontSize="12"/>
  <ComboBoxItem Content="Georgia" Tag="Georgia" FontFamily="Georgia" FontSize="12"/>
  <ComboBoxItem Content="Lucida Sans Unicode" Tag="Lucida Sans Unicode" FontFamily="Lucida Sans Unicode" FontSize="12"/>
  <ComboBoxItem Content="Times New Roman" Tag="Times New Roman" FontFamily="Times New Roman" FontSize="12"/>
  <ComboBoxItem Content="Trebuchet MS" Tag="Trebuchet MS" FontFamily="Trebuchet MS" FontSize="12"/>
  <ComboBoxItem Content="Verdana" Tag="Verdana" FontFamily="Verdana" FontSize="12"/>
  <ComboBoxItem Content="Webdings" Tag="Webdings" FontSize="12"/>
</ComboBox>

<ComboBox Canvas.Left="168" Canvas.Top="64" Height="23" Width="75" Name="Size">
  <ComboBoxItem Content="8" Tag="8"/>
  <ComboBoxItem Content="10" Tag="10"/>
  <ComboBoxItem Content="12" Tag="12"/>
  <ComboBoxItem Content="16" Tag="16" IsSelected="True"/>
  <ComboBoxItem Content="20" Tag="20"/>
  <ComboBoxItem Content="24" Tag="24"/>
  <ComboBoxItem Content="28" Tag="28"/>
  <ComboBoxItem Content="36" Tag="36"/>
  <ComboBoxItem Content="48" Tag="48"/>
  <ComboBoxItem Content="72" Tag="72"/>
</ComboBox>

<ComboBox Canvas.Left="249" Canvas.Top="64" Height="23" Width="75" Name="Colour">
  <ComboBoxItem Tag="FF000000" IsSelected="True">
    <Rectangle Width="25" Height="14" Fill="Black"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF808080">
    <Rectangle Width="25" Height="14" Fill="Gray"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFF0000">
    <Rectangle Width="25" Height="14" Fill="Red"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFFA500">
    <Rectangle Width="25" Height="14" Fill="Orange"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFFFF00">
    <Rectangle Width="25" Height="14" Fill="Yellow"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF008000">
    <Rectangle Width="25" Height="14" Fill="Green"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF00FFFF">
    <Rectangle Width="25" Height="14" Fill="Cyan"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF0000FF">
    <Rectangle Width="25" Height="14" Fill="Blue"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FFFF00FF">
    <Rectangle Width="25" Height="14" Fill="Magenta"/>
  </ComboBoxItem>
  <ComboBoxItem Tag="FF800080">
    <Rectangle Width="25" Height="14" Fill="Purple"/>
  </ComboBoxItem>
</ComboBox>

See below:

MainPage with Toolbar Buttons and ComboBoxes

Step 10

Again while still in the XAML Pane below the "</Canvas>" and above the "</Grid>" Tag, type the following RichTextArea XAML:

<RichTextArea Height="205" Width="400" Margin="0,95,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" 
TextWrapping="Wrap" BorderThickness="0" Name="Editor"/>

See below:

MainPage with Toolbar Buttons, ComboBoxes and RichTextArea

Step 11

Right Click on the Page or the entry for "MainPage.xaml" in Solution Explorer and choose the "View Code" option. In the Code View above the "Partial Public Class MainPage" line type the following:

Imports System.Xml.Linq
Imports System.Windows.Printing

See Below:

MainPage.xaml Imports

Step 12

While still in the Code View for MainPage.xaml, below the "End Sub" for "Public Sub New()" Constructor type the following Sub:

Private Sub Read(ByRef Stream As IO.Stream, ByRef Blocks As BlockCollection)
  Dim _doc As XDocument = XDocument.Load(Stream)
  Dim _colour As String
  For Each _element As XElement In _doc.Descendants("Paragraph")
    Dim _paragraph As New Paragraph
    _paragraph.FontFamily = New FontFamily(_element.Attribute(XName.[Get]("FontFamily")).Value)
    _paragraph.FontSize = Double.Parse(_element.Attribute(XName.[Get]("FontSize")).Value)
    _paragraph.FontStretch = DirectCast(GetType(FontStretches).GetProperty(
    _element.Attribute(XName.[Get]("FontStretch")).Value).GetValue(Nothing, Nothing), FontStretch)
    _paragraph.FontStyle = DirectCast(GetType(FontStyles).GetProperty(
    _element.Attribute(XName.[Get]("FontStyle")).Value).GetValue(Nothing, Nothing), FontStyle)
    _paragraph.FontWeight = DirectCast(GetType(FontWeights).GetProperty(
    _element.Attribute(XName.[Get]("FontWeight")).Value).GetValue(Nothing, Nothing), FontWeight)
    _colour = _element.Attribute(XName.[Get]("Foreground")).Value
    _colour = _colour.Remove(0, 1)
    _paragraph.Foreground = New SolidColorBrush(Color.FromArgb(
      Byte.Parse(_colour.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
      Byte.Parse(_colour.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
      Byte.Parse(_colour.Substring(4, 2), System.Globalization.NumberStyles.HexNumber),
      Byte.Parse(_colour.Substring(6, 2), System.Globalization.NumberStyles.HexNumber)))
    For Each _inline As XElement In _element.Descendants("Inline")
      If _inline.Attribute(XName.[Get]("Type")).Value = "Run" Then
        Dim _run As New Run
        _run.FontFamily = New FontFamily(_element.Attribute(XName.[Get]("FontFamily")).Value)
        _run.FontSize = Double.Parse(_element.Attribute(XName.[Get]("FontSize")).Value)
        _run.FontStretch = DirectCast(GetType(FontStretches).GetProperty(
        _element.Attribute(XName.[Get]("FontStretch")).Value).GetValue(Nothing, Nothing), FontStretch)
        _run.FontStyle = DirectCast(GetType(FontStyles).GetProperty(
        _element.Attribute(XName.[Get]("FontStyle")).Value).GetValue(Nothing, Nothing), FontStyle)
        _run.FontWeight = DirectCast(GetType(FontWeights).GetProperty(
        _element.Attribute(XName.[Get]("FontWeight")).Value).GetValue(Nothing, Nothing), FontWeight)
        _colour = _element.Attribute(XName.[Get]("Foreground")).Value
        _colour = _colour.Remove(0, 1)
        _run.Foreground = New SolidColorBrush(Color.FromArgb(
          Byte.Parse(_colour.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
          Byte.Parse(_colour.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
          Byte.Parse(_colour.Substring(4, 2), System.Globalization.NumberStyles.HexNumber),
          Byte.Parse(_colour.Substring(6, 2), System.Globalization.NumberStyles.HexNumber)))
        If _inline.Attribute(XName.[Get]("TextDecorations")).Value = "Underline" Then
          _run.TextDecorations = TextDecorations.Underline
        End If
        _run.Text = _inline.Attribute(XName.[Get]("Text")).Value
        _paragraph.Inlines.Add(_run)
      End If
    Next
    Blocks.Add(_paragraph)
  Next
End Sub

See Below:

MainPage Read Sub

Step 13

While still in the Code View for MainPage.xaml, below the "End Sub" for "Private Sub Read(...)" type the following Function:

Private Function Write(ByRef Blocks As BlockCollection) As String
  Dim _write As New Text.StringBuilder
  Dim _doc = From block In Blocks _
  From inline In TryCast(block, Paragraph).Inlines
    Where inline.GetType Is GetType(InlineUIContainer) _
    Select inline
  If _doc.Count = 0 Then
    _write.Append("<doc>")
    For Each _block As Block In Blocks
      Dim _paragraph As New Paragraph
      _write.Append("<Paragraph ")
      _write.Append("Name='" & _paragraph.Name &"' ")
      _write.Append("FontFamily='" & _paragraph.FontFamily.ToString & "' ")
      _write.Append("FontSize='" & _paragraph.FontSize & "' ")
      _write.Append("FontStretch='" & _paragraph.FontStretch.ToString & "' ")
      _write.Append("FontStyle='" & _paragraph.FontStyle.ToString & "' ")
      _write.Append("FontWeight='" & _paragraph.FontWeight.ToString & "' ")
      _write.Append("Foreground='" & TryCast(_paragraph.Foreground, SolidColorBrush).Color.ToString & "'>")
      For Each _inline In TryCast(_block, Paragraph).Inlines
        If TypeOf _inline Is Run Then
          Dim _run As Run = TryCast(_inline, Run)
          _write.Append("<Inline Type='Run' ")
          _write.Append("Name='" & _run.Name & "' ")
          _write.Append("FontFamily='" & _run.FontFamily.ToString & "' ")
          _write.Append("FontSize='" & _run.FontSize & "' ")
          _write.Append("FontStretch='" & _run.FontStretch.ToString & "' ")
          _write.Append("FontStyle='" & _run.FontStyle.ToString & "' ")
          _write.Append("FontWeight='" & _run.FontWeight.ToString & "' ")
          _write.Append("Foreground='" & TryCast(_run.Foreground, SolidColorBrush).Color.ToString & "' ")
          _write.Append("Text='" & _run.Text & "' ")
          _write.Append("TextDecorations='" & If(_run.TextDecorations Is Nothing, "", "Underline") & "'/>")
        End If
      Next
      _write.Append("</Paragraph>")
    Next
    _write.Append("</doc>")
    Return _write.ToString
  Else
    Return Nothing
  End If
End Function

See Below:

MainPage Write Function

Step 14

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "New" Button Control and type in the New_Click Sub:

If MessageBox.Show("Start a New Document?", "Rich Text Editor", _
    MessageBoxButton.OKCancel) = MessageBoxResult.OK Then
  Editor.Blocks.Clear()
End If

See Below:

New Button Click Event

Step 15

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Open..." Button and type in the Open_Click Sub:

Dim OpenDialog As New OpenFileDialog
OpenDialog.Filter = "Saved Files (*.sav)|*.sav"
If OpenDialog.ShowDialog Then
  Try
    If OpenDialog.File.Exists Then
      Editor.Blocks.Clear()
      Read(OpenDialog.File.OpenRead, Editor.Blocks)
    End If
  Catch ex As Exception
    ' Ignore Errors
  End Try
End If

See Below:

Open Button Click Event

Step 16

Return to the Designer View again, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Save..." Button and type in the Save_Click Sub:

Dim SaveDialog As New SaveFileDialog
SaveDialog.Filter = "Saved Files (*.sav)|*.sav"
If SaveDialog.ShowDialog Then
  Try
    Using FileStream As IO.StreamWriter = _
        New IO.StreamWriter(SaveDialog.OpenFile)
      FileStream.Write(Write(Editor.Blocks))
    End Using
  Catch ex As Exception
    ' Ignore Errors
  End Try
End If

See Below:

Save Button Click Event

Step 17

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Print" Button Control and type in the Print_Click Sub:

Dim _print As New PrintDocument
_print.DocumentName = "Rich Text Editor"
AddHandler _print.PrintPage, Sub(s As Object, args As PrintPageEventArgs)
    args.PageVisual = Editor
    args.HasMorePages = False
  End Sub
AddHandler _print.EndPrint, Sub(s As Object, args As EndPrintEventArgs)
    MessageBox.Show("Document Printed", _
      "Rich Text Editor", MessageBoxButton.OK)
  End Sub
_print.Print()
Editor.Focus()

See Below:

Print Button Click Event

Step 18

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Bold" Button and type in the Bold_Click Sub:

If Editor.Selection.Text.Length > 0 Then ' Text Selected
  If TypeOf Editor.Selection.GetPropertyValue(Run.FontWeightProperty) Is FontWeight _
      AndAlso DirectCast(Editor.Selection.GetPropertyValue( _
        Run.FontWeightProperty), FontWeight) = FontWeights.Normal Then
    Editor.Selection.SetPropertyValue(Run.FontWeightProperty, FontWeights.Bold)
  Else
    Editor.Selection.SetPropertyValue(Run.FontWeightProperty, FontWeights.Normal)
  End If
End If
Editor.Focus()

See Below:

Bold Button Click Event

Step 19

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Italic" Button and type in the Italic_Click Sub:

If Editor.Selection.Text.Length > 0 Then ' Text Selected
  If TypeOf Editor.Selection.GetPropertyValue(Run.FontStyleProperty) Is FontStyle _
      AndAlso DirectCast(Editor.Selection.GetPropertyValue( _
        Run.FontStyleProperty), FontStyle) = FontStyles.Normal Then
    Editor.Selection.SetPropertyValue(Run.FontStyleProperty, FontStyles.Italic)
  Else
    Editor.Selection.SetPropertyValue(Run.FontStyleProperty, FontStyles.Normal)
  End If
End If
Editor.Focus()

See Below:

Italic Button Click Event

Step 20

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Underline" Button and type in the Underline_Click Sub:

If Editor.Selection.Text.Length > 0 Then ' Text Selected
  If Editor.Selection.GetPropertyValue(Run.TextDecorationsProperty) Is Nothing Then
    Editor.Selection.SetPropertyValue(Run.TextDecorationsProperty, TextDecorations.Underline)
  Else
    Editor.Selection.SetPropertyValue(Run.TextDecorationsProperty, Nothing)
  End If
End If
Editor.Focus()

See Below:

Underline Button Click Event

Step 21

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the "Time Date" Button and type in the TimeDate_Click Sub:

Editor.Selection.Text = Format(Now, "HH:mm dd/MM/yyyy")
Editor.Focus()

See Below:

Time Date Button Click Event

Step 22

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the First or Left-most ComboBox (Font) and type in the Font_SelectionChanged Sub:

If Editor IsNot Nothing AndAlso Editor.Selection.Text.Length > 0 Then ' Text Selected
  Editor.Selection.SetPropertyValue(Run.FontFamilyProperty, _
    New FontFamily(CType(Font.SelectedItem, ComboBoxItem).Tag))
  Editor.Focus()
End If

See Below:

Font ComboBox SelectionChanged Event

Step 23

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the Second ComboBox (Size) and type in the Size_SelectionChanged Sub:

If Editor IsNot Nothing AndAlso Editor.Selection.Text.Length > 0 Then ' Text Selected
  Editor.Selection.SetPropertyValue(Run.FontSizeProperty, _
    Double.Parse(TryCast(Size.SelectedItem, ComboBoxItem).Tag))
  Editor.Focus()
End If

See Below:

Size ComboBox SelectionChanged Event

Step 24

Return to the Designer View, by selecting the "MainPage.xaml" Tab, or Right Click on the Page or the Entry for "MainPage.xaml" in Solution Explorer and choose the "View Designer" option.
Double Click on the Third ComboBox (Colour) and type in the Colour_SelectionChanged Sub:

If Editor IsNot Nothing AndAlso Editor.Selection.Text.Length > 0 Then ' Text Selected
  Dim _colour As String = CType(Colour.SelectedItem, ComboBoxItem).Tag
  Dim _brush As New SolidColorBrush(Color.FromArgb(
    Byte.Parse(_colour.Substring(0, 2), System.Globalization.NumberStyles.HexNumber),
    Byte.Parse(_colour.Substring(2, 2), System.Globalization.NumberStyles.HexNumber),
    Byte.Parse(_colour.Substring(4, 2), System.Globalization.NumberStyles.HexNumber),
    Byte.Parse(_colour.Substring(6, 2), System.Globalization.NumberStyles.HexNumber)))
  Editor.Selection.SetPropertyValue(Run.ForegroundProperty, _brush)
  Editor.Focus()
End If

See Below:

Colour ComboBox SelectionChanged Event

Step 25

Save the Project as you have now finished the Silverlight application. Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in a new Web Browser window:

Application Running

Step 26

You can Type into the RichTextArea, and then apply Formatting, Fonts, Sizes and Colours - then Save the Document to Open later, see below:

Rich Text Editor

Step 27

Close the Browser window by clicking on the Close Button Close on the top right of the Web Browser to Stop the application.

This is a very simple Rich Text Editor with some of the common features supported by Silverlight featured, see if you can add more features to this application such as Text Alignment, it is up to you!