Rich Text Editor Lab by day66380

VIEWS: 347 PAGES: 26

									Hands-On Lab
Silverlight 4 – Rich Text Editor
Rich Text Editor



Contents



Introduction ........................................................................................................................................................ 3
Exercise 1 – Getting Started ................................................................................................................................ 4
       Task 1 – Building a Text Editor UI ................................................................................................................ 5
       Task 2 – Applying Different Styles ............................................................................................................. 11
Exercise 2 – Working with the RichTextArea control ........................................................................................ 12
       Task 1 – Formatting Text ........................................................................................................................... 12
       Task 2 – Embedded elements ................................................................................................................... 15
       Task 3 – Persisting content........................................................................................................................ 17
Exercise 3 – Advanced Text Services ................................................................................................................. 20
       Task 1 – Clipboard Support ....................................................................................................................... 20
       Task 2 – Printing from Silverlight .............................................................................................................. 21
Exercise 4 – Multilingual Support...................................................................................................................... 22
       Task 1 –BiDi (Bi-Directional) support ........................................................................................................ 22
       Task 2 –Culture based UI with Resources ................................................................................................. 23
Conclusion ......................................................................................................................................................... 26
Rich Text Editor




Introduction
Silverlight 4 offers many new features for text editing including a new Rich-Text editor control, Clipboard
support, Printing abilities and BiDi (Bidirectional) text support for input and output. The new Rich-Text
editor control (RichTextArea) enables applications to show rich text and allows users to input rich text
including formatted text (Bold, Italic, Underline, Font family, Font size & Font color) & embedded elements
such as Hyperlinks and Images.
In this Lab we will learn how to build a text editor that supports rich text, clipboard copy & paste and
printing. We'll also learn how we can use the new BiDi support and the culture based Resources in
Silverlight 4 to customize the application's UI according to the client's culture.
Estimated completion time for this lab is 60 minutes.
Rich Text Editor




Exercise 1 – Getting Started
The goal of this exercise is to familiarize the student with existing starter application and build the skeleton
UI of the application.
    1. Start Visual Studio 2010 Beta 2
    2. On the File menu click Open  Project/Solution…
                   a. Alternatively, from Visual Studio Start Page click “Open Project…”
    3.   At “Open Project” dialog navigate to the Lab installation folder
    4. Navigate to “TextEditor\Source\Ex01-GettingStarted\begin” folder
    5. Click “TextEditor.sln” file and the click “Open” button
    6. Take some time to familiarize yourself with the Starter application
                   a. Points of interest here are:
                            MainPage.xaml
                            MainPage.xaml.cs
                            Strings.resx
                            BoolToFlowDirectionConverter.cs

                            TextSelectionToIsEnabledConverter.cs
                            InsertURL.xaml

                            InsertURL.xaml.cs
    7. Set the TextEditor.Web project as the startup project, by right clicking the project in the Solution
       Explorer and selecting “Set as Startup”
    8. Press F5 or click Debug  Start Debugging to Run the application
    9. Use the application to familiarize yourself with it. When finished close the browser window
Rich Text Editor



Task 1 – Building a Text Editor UI
In order to use the rich text formatting the RichTextArea control offers, we need a set of buttons that will
allows us to perform formatting of the text, so let's start by building a Tool Box. In this exercise we will
create user Tool Box interface by adding buttons and binding them to resources.
    1. If you haven't opened the Starter project open it now (see previous section for detailed
       instructions)
    2. Open the MainPage.xaml file. Look at the Grid control definition; notice the grid has 4 rows,
       currently only one row (row index 2) is used.
    3. We will add a StackPanel control before the RichTextArea control. This will act as a container for
       the ToolBox items. Add the following code inside the Grid's XAML code
        XAML
        <StackPanel x:Name="CommandToolbar" Orientation="Horizontal" Grid.Row="1">
               <!--New-->
               <Button x:Name="btnNew">
               <Button.Content>
                      <Image Source="Images/New.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_New, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
               </Button>
        </StackPanel>

    4. Examine the above XAML - notice that the button's ToolTip content is data bound to a
       StaticResource name "localizedStrings". If you look in the beginning of the file, you'll notice this
       resource:
        XAML
        <local:Strings x:Key="localizedStrings"/>

    5. The "Strings" type is a Resource (.resx file) located in the Project's tree




        Figure 1
        Project structure
Rich Text Editor



    6. Open the "Strings.resx" resource file, notice how we have a representing string for each text we
       wish to present in the application




        Figure 2
        Resources Designer
    7. As you can see, the ToolTip's content will show "Create new document". In the last exercise we will
       change an application's culture and create multilingual resource files.
    8. Return to the "MainPage.xaml" and place the rest of the ToolBox content beneath the "New"
       button
        XAML
        <!--Open Existing-->
        <Button x:Name="btnOpen">
               <Button.Content>
                      <Image Source="Images/Open.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Open, Source={StaticResource
                                          localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Save Existing-->
        <Button IsEnabled="{Binding IsDirty}" x:Name="btnSave">
Rich Text Editor



               <Button.Content>
                      <Image Source="Images/Save.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Save, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Print document-->
        <Button x:Name="btnPrint">
               <Button.Content>
                      <Image Source="Images/Print.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Print, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Cut-->
        <Button x:Name="btnCut">
               <Button.Content>
                      <Image Source="Images/Cut.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Cut, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Copy-->
        <Button x:Name="btnCopy">
               <Button.Content>
                      <Image Source="Images/Copy.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Copy, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Paste-->
        <Button x:Name="btnPaste">
               <Button.Content>
                      <Image Source="Images/Paste.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
Rich Text Editor



                      <ToolTip Content="{Binding tooltip_Paste, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Fonts Combo-->
        <ComboBox x:Name="cmbFonts" Width="160"
                      FontFamily="{Binding RelativeSource={RelativeSource Self},
                             Path=SelectedItem.FontFamily}"
                      FontSize="{Binding RelativeSource={RelativeSource Self},
                             Path=SelectedItem.FontSize}">
               <ComboBoxItem Content="Arial" Tag="Arial" FontFamily="Arial"
                             FontSize="12"/>
               <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="Portable User Interface" Tag="{x:Null}"
                             IsSelected="True" FontFamily="Portable User Interface"
                             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>

        <!--Font Sizes-->
        <ComboBox x:Name="cmbFontSizes" Width="80">
               <ComboBoxItem Content="8 pt" Tag="8"/>
               <ComboBoxItem Content="9 pt" Tag="9"/>
               <ComboBoxItem Content="10 pt" Tag="10"/>
               <ComboBoxItem Content="11 pt" Tag="11" IsSelected="True"/>
               <ComboBoxItem Content="12 pt" Tag="12"/>
               <ComboBoxItem Content="14 pt" Tag="14"/>
               <ComboBoxItem Content="16 pt" Tag="16"/>
               <ComboBoxItem Content="18 pt" Tag="18"/>
               <ComboBoxItem Content="20 pt" Tag="20"/>
               <ComboBoxItem Content="22 pt" Tag="22"/>
               <ComboBoxItem Content="24 pt" Tag="24"/>
               <ComboBoxItem Content="26 pt" Tag="26"/>
Rich Text Editor



               <ComboBoxItem   Content="28   pt"   Tag="28"/>
               <ComboBoxItem   Content="36   pt"   Tag="36"/>
               <ComboBoxItem   Content="48   pt"   Tag="48"/>
               <ComboBoxItem   Content="72   pt"   Tag="72"/>
        </ComboBox>

        <!--Buttons-->
        <Button x:Name="btnBold">
               <Button.Content>
                      <Image Source="Images/Bold.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Bold, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <Button x:Name="btnItalic">
               <Button.Content>
                      <Image Source="Images/Italic.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Italic, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <Button x:Name="btnUnderline">
               <Button.Content>
                      <Image Source="Images/Underline.png"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Underline, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <!--Text Color-->
        <ComboBox x:Name="cmbFontColors" Width="100">
               <ComboBoxItem Content="Red" Tag="FFFF0000"/>
               <ComboBoxItem Content="Green" Tag="FF008000"/>
               <ComboBoxItem Content="Blue" Tag="FF0000FF"/>
               <ComboBoxItem Content="Yellow" Tag="FFFFFF00"/>
               <ComboBoxItem Content="Black" Tag="FF000000" IsSelected="True"/>
        </ComboBox>

        <!--Hyperlink & Image buttons-->
        <Button x:Name="btnHyperlink">
               <Button.Content>
Rich Text Editor



                      <Image Source="Images/Hyperlink.png" Width="16" Height="16"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Hyperlink, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

        <Button x:Name="btnImage">
               <Button.Content>
                      <Image Source="Images/Image.png" Width="16" Height="16"/>
               </Button.Content>
               <ToolTipService.ToolTip>
                      <ToolTip Content="{Binding tooltip_Image, Source={StaticResource
                                   localizedStrings}}"></ToolTip>
               </ToolTipService.ToolTip>
        </Button>

    9. Before compiling the code, we'll need to add some images to the project. Under the Solution
       Explorer, right-click on the "TextEditor" Project and select Add  New Folder and name the new
       folder "Images".




        Figure 3
        Add New Folder
    10. Right-click the "Images" folder and select Add  Existing Item…, navigate to the Lab installation
        folder and from there navigate to "\Helpers\Images", select all the images and press "Add".
    11. Compile and Run the project and you will see a new Toolbox above the RichTextArea control.
    12. In this exercise we created a Tool Box with a buttons and other controls to decorate RichTextArea.
        In the following exercises we will write the necessary code to make them work.
Rich Text Editor



Task 2 – Applying Different Styles
In this exercise we will style the user interface in order to give our application non-standard look and feel.
We prepared styles in order to save you time. During this lab you will add them to application resources.
    1. Before we dive into the code and implement the Toolbox buttons, let's give our application a new,
       polished style. Open the "App.xaml" file and add the following XAML inside the Application element
        XAML
        <Application.Resources>
               <ResourceDictionary>
                      <ResourceDictionary.MergedDictionaries>
                             <ResourceDictionary Source="Styles.xaml" />
                      </ResourceDictionary.MergedDictionaries>
               </ResourceDictionary>
        </Application.Resources>

    2. Open the "Styles.xaml" file and examine the different control's style. This file defines implicit styles
       that will give our application a darker look.
    3. Open the "MainPage.xaml.cs" file and add the following static method
        C#
        private static LinearGradientBrush GetLinearBrush(Color startColor,
                                                          Color endColor)
        {
               LinearGradientBrush brush = new LinearGradientBrush();
               GradientStop colorStop1 = new GradientStop();
               colorStop1.Color = startColor;
               GradientStop colorStop2 = new GradientStop();
               colorStop2.Color = endColor;
               colorStop2.Offset = 1;
               brush.StartPoint = new System.Windows.Point(0.5, 1);
               brush.EndPoint = new System.Windows.Point(0.5, 0);
               brush.GradientStops = new GradientStopCollection
                                         { colorStop1, colorStop2 };
               return brush;
        }

    4. Add the following line to the end of the MainPage class constructor, to set the gradient background
       of the application:
        C#
        LayoutRoot.Background = GetLinearBrush(Color.FromArgb(255, 23, 23, 23),
                                               Color.FromArgb(255, 10, 10, 10));

    5. Compile and run the application. The application style is now darker than before and has non-
       standard look and feel.
Rich Text Editor




Exercise 2 – Working with the
RichTextArea control
In this exercise will learn about the different text formatting options we have in the RichTextArea control,
including Bold, Italic & Underline text styles, changing font family, size and color and more.




Task 1 – Formatting Text
In this exercise we will handle the Tool Box controls events and use RichTextArea features in order to style
the text.

    1. Open the "MainPage.xaml" file and find the button named "btnBold". Add a new "Click" event
       handler (use the default name)




        Figure 4
        Event Handler Generation from XAML Editor
    2. Right-click " btnBold_Click" and select "Navigate to Event Handler" from the context menu




        Figure 5
        Navigate to Event Handler from XAML Editor
    3. The last action will take you into the source code editor, to the event handler function:
        C#
        private void btnBold_Click(object sender, RoutedEventArgs e)
        {

        }

    4. Since we want to set the selected text to bold, we'll add the following "if" statement to check
       whether the user selected some text prior to pressing the button
Rich Text Editor



        C#
        if (rtb != null && rtb.Selection.Text.Length > 0)
        {

        }
        SetBackFocus();

    5. Once we have a selection, all that is left to do is to change the font's weight from normal to bold or
       vice versa, according to whether the button is toggled or not. We will need to check the current
       font style and apply the opposite (in case the selection is mixed we'll remove the bold style). Add
       the following code inside the "if" statement to perform the style modification
        C#
        if (rtb.Selection.GetPropertyValue(Run.FontWeightProperty) is FontWeight &&
               ((FontWeight)rtb.Selection.GetPropertyValue(Run.FontWeightProperty))
               == FontWeights.Normal)
               rtb.Selection.SetPropertyValue(Run.FontWeightProperty,
                                                FontWeights.Bold);
        else
               rtb.Selection.SetPropertyValue(Run.FontWeightProperty,
                                                FontWeights.Normal);


    6. Compile the code and run the application. Enter some text, select it and press the bold button. The
       text has become bold, press the bold button again and the text has returned to normal. If you
       select mixed text (some characters bold, some normal) and press the bold button, the text will
       return to normal.
    7. Apply steps 1-5, this time for the "btnItalic" button, place the following code in the button's default
       event handler
        C#
        if (rtb != null && rtb.Selection.Text.Length > 0)
        {
               if (rtb.Selection.GetPropertyValue(Run.FontStyleProperty) is FontStyle &&
                      ((FontStyle)rtb.Selection.GetPropertyValue(Run.FontStyleProperty))
                      == FontStyles.Normal)
                      rtb.Selection.SetPropertyValue(Run.FontStyleProperty,
                                                       FontStyles.Italic);
               else
                      rtb.Selection.SetPropertyValue(Run.FontStyleProperty,
                                                       FontStyles.Normal);
        }
        SetBackFocus();

    8. Apply steps 1-5, this time for the "btnUnderline" button, place the following code in the button's
       default event handler
        C#
Rich Text Editor



        if (rtb != null && rtb.Selection.Text.Length > 0)
        {
               if (rtb.Selection.GetPropertyValue(Run.TextDecorationsProperty) == null)
                      rtb.Selection.SetPropertyValue(Run.TextDecorationsProperty,
                                                       TextDecorations.Underline);
               else
                      rtb.Selection.SetPropertyValue(Run.TextDecorationsProperty, null);
        }
        SetBackFocus();


    9. Next, we'll handle font family modification. When the user changes the font in the font's ComboBox
       control, we'll change the font family of the current selected text. Find the ComboBox named
       "cmbFonts", and add a default event handler for the "SelectionChanged" event. Open the event
       handler function and add the following code to it:
        C#
        if (rtb != null && rtb.Selection.Text.Length > 0)
        {
               rtb.Selection.SetPropertyValue(Run.FontFamilyProperty,
                      new FontFamily((cmbFonts.SelectedItem as
                                          ComboBoxItem).Tag.ToString()));
        }
        SetBackFocus();

    10. Let's do the same to the text size. Find the ComboBox named "cmbFontSize", add a default event
        handler for the "SelectionChanged" event and add the following code to the event handler function
        C#
        if (rtb != null && rtb.Selection.Text.Length > 0)
        {
               rtb.Selection.SetPropertyValue(Run.FontSizeProperty,
                      double.Parse((cmbFontSizes.SelectedItem as
                             ComboBoxItem).Tag.ToString()));
        }
        SetBackFocus();

    11. Find the "cmbFontColors" ComboBox, examine how each color is represented as a string of HEX
        values representing the color and stored in the "Tag" property of the ComboBoxItem element. In
        order to break that string into ARGB (Alpha/Red/Green/Blue) format, we'll need to do some
        parsing. Create a default event handler for the "SelectionChanged" event and add the following
        code to the event handler function
        C#
        if (rtb != null && rtb.Selection.Text.Length > 0)
        {
               string color = (cmbFontColors.SelectedItem as ComboBoxItem).Tag.ToString();
Rich Text Editor



                   SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(
                          byte.Parse(color.Substring(0, 2),
                                 System.Globalization.NumberStyles.HexNumber),
                          byte.Parse(color.Substring(2, 2),
                                 System.Globalization.NumberStyles.HexNumber),
                          byte.Parse(color.Substring(4, 2),
                                 System.Globalization.NumberStyles.HexNumber),
                          byte.Parse(color.Substring(6, 2),
                                 System.Globalization.NumberStyles.HexNumber)));

               rtb.Selection.SetPropertyValue(Run.ForegroundProperty, brush);
        }
        SetBackFocus();


We just applied formatting over the text in the RichTextArea.
Task 2 – Embedded elements
In this exercise we will enrich the textual content of the RichTextArea with hyperlink and image.
    1. Open the file "MainPage.xaml" and locate the "btnImage" button. Add a default event handler for
       the "Click" event, and navigate to the event handler function.
    2. In order to add an image to the RichTextArea we need to create an InlineUIContainer object that
       will contain the image presented by the RichTextArea. Add the following code to the event handler
       function:
        C#
        InlineUIContainer container = new InlineUIContainer();

    3. Now that we have a container, we can load a sample image to it (you can find the image in the
       ClientBin folder in the Web Project. In real life, we'll probably offer the user to select an image from
       the disk). Add the following code to load an image and place it in the container:
        C#
        Image img = DocumentPersister.createImageFromUri(new Uri("Sample.png",
                                                            UriKind.RelativeOrAbsolute));
        container.Child = img;

    4. All that is left is to add the container to the rich text control. Place the next line at the end of the
       method:
        C#
        rtb.Selection.Insert(container);

    5. Compile and run the application. Press the "insert image" button (last in the toolbox) – an image
       will appear in the rich text control.
    6. To add a hyperlink to the rich text control, we will use a child window to allow the user to input a
       hyperlink and a description for it.
Rich Text Editor



    7.    The ChildWindow class was introduced in Silverlight 3 and is used to implement popup windows
         you can interact with. Find the file "InsertURL.xaml" and the file "InsertURL.xaml.cs" and familiarize
         yourself with them. Examine the validation code in the "InsertURL.xaml.cs" class constructor.
    8. Open the file "MainPage.xaml", find the "btnHyperlink" button and add an event handler for the
       "Click" event. To show the InsertURL child window, add the following code to the event handler
       function:
         C#
         InsertURL cw = new InsertURL();
         cw.HasCloseButton = false;
         cw.Show();

    9. The above code will show the child window, but after confirming the URL, we need to fetch it from
       the child window and place it in the rich text area. Add the following code to handle the "Close"
       event of the child window (place the code before calling the "Show" method)
         C#
         cw.Closed += (s, args) =>
         {
                if (cw.DialogResult.Value)
                {

                   }
         };

    10. Next, we'll create a Hyperlink object, set the URL and the text to place it inside the rich text area.
        Place the following code inside the "if" statement from the last step.
         C#
         Hyperlink hyperlink = new Hyperlink();
         hyperlink.TargetName = "_blank";
         hyperlink.NavigateUri = new Uri(cw.txtURL.Text);

         if (cw.txtURLDesc.Text.Length > 0)
                hyperlink.Inlines.Add(cw.txtURLDesc.Text);
         else
                hyperlink.Inlines.Add(cw.txtURL.Text);

         rtb.Selection.Insert(hyperlink);


    11. Compile and run the application. Press the hyperlink button and input a valid URL and a description.
        Press "OK". Notice the hyperlink is added to the rich text area. Now our text editor has hyperlinks
        and images elements in addition to write and style the text
Rich Text Editor



Task 3 – Persisting content
Now that our editor supports inputting text and styling it, let's see how we can save these documents. We
prepared functionality of serializing and deserializing the content in order to save you time during the lab.
    1. Before we allow the user to clear the document's content, we need to check if the document has
       been changed. In order to do that, we'll use a Boolean property called "IsDirty" that will be true if
       the text area has text in it and false if it's empty. Open the file "MainPage.xaml", locate the
       RichTextArea control and add a default event handler for the "KeyUp" event. Navigate to the event
       handler function and add the following code to the function:
        C#
        if (rtb.Blocks.Count > 1 ||
             (rtb.Blocks.Count == 1 &&
             (rtb.Blocks[0] as Paragraph).Inlines.Count > 0))
             IsDirty = true;
        else
             IsDirty = false;



    2. Now that we know whether the document is "dirty" or not, we can implement the "new" button.
       Open the file "MainPage.xaml", locate the "btnNew" button and add a default event handler for the
       "Click" event. Add the following code to the event handler function:
        C#
        if (IsDirty)
        {
            Save();
        }
        rtb.Blocks.Clear();
        IsDirty = false;



    3. As you can see, if the user tries to clear an existing document, he is offered a chance to save the
       document, so let's implement the save option. Go back to the "MainPage.xaml", locate the
       "btnSave" button and add a default event handler for the "click" event, then navigate to the event
       handler function. Create a new private method named Save and then call the Save() method in the
       btnSave’s “click” event handler.
    4. In order to save a rich text area, we need to serialize its content. For this operation, we'll use a
       helper class that uses the Visitor pattern to iterate through the content of the rich text area. Place
       the following lines in the Save method (as you can see, the helper class currently doesn't support
       saving documents with images)
        C#
        StringBuilder sb = DocumentPersister.prepareDocumentXML(rtb.Blocks);
Rich Text Editor



        if (sb == null)
        {
               MessageBox.Show("Saving documents with images is not supported");
               return;
        }

    5. Once we have the content of the rich text area, prompt the user to select where he wants to save
       the file, for that use the SaveFileDialog class introduced in Silverlight 3. Place the following code
       after the "if" statement:
        C#
        SaveFileDialog sfd = new SaveFileDialog();
        sfd.DefaultExt = ".sav";
        sfd.Filter = "Saved Files|*.sav|All Files|*.*";

        if (sfd.ShowDialog().Value)
        {

        }

    6. All that is left to do is to take the content, write it into the selected file and reset the "IsDirty" flag.
       Add the rest of the save code inside the "if" statement:
        C#
        using (FileStream fs = (FileStream)sfd.OpenFile())
        {
            System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding();
            byte[] buffer = enc.GetBytes(sb.ToString());
            fs.Write(buffer, 0, buffer.Length);
            fs.Close();
            IsDirty = false;
        }

    7. Before we can test this code, we need to be able to open the saved file. Open the file
       "MainPage.xaml" and locate the "btnOpen" button. Add a default event handler for the "Click"
       event and navigate to it. Since opening a document requires clearing the existing document, let's
       start by calling the clear code we've written. Place the following code in the event handler function:
        C#
        btnNew_Click(sender, e);

    8. Next, we will use the OpenFileDialog class to ask the user to select which document to open. Place
       the following code after calling the btnNew_Click method:
        C#
        OpenFileDialog ofd = new OpenFileDialog();
        ofd.Multiselect = false;
        ofd.Filter = "Saved Files|*.sav|All Files|*.*";
Rich Text Editor



        if (ofd.ShowDialog().Value)
        {

        }

    9. Once the user selects a file, read its content and pass it through the helper's class deserializer
       method. In the "if" statement place the following code to perform these actions:
        C#
        FileInfo fi = ofd.File;
        System.Xml.XmlReader r = System.Xml.XmlReader.Create(fi.OpenText());

        DocumentPersister.parseSavedDocument(r, rtb.Blocks);
        r.Close();

    10. Compile and run the application. Enter some text and hyperlinks and test the Save & Load features.
        Please note the helper class that serializes rich text to XML currently doesn't support saving images.
        At the end of the exercise we have an almost fully functional Text Editor, with basic features such as
        font styling, embedding hyperlinks and images, and saving and loading documents.
Rich Text Editor




Exercise 3 – Advanced Text Services
In this exercise we'll learn how we can perform advanced operations such as using the clipboard to copy &
paste text into the rich text area and print our rich text content.


Task 1 – Clipboard Support
Silverlight 4 provides support for clipboard operations. In our case we will create basic clipboard operations
copy/paste/cut.
    1. Open the "MainPage.xaml" file, and locate the following 3 buttons: "btnCut", "btnCopy" and
       "btnPaste". Add a default event handler for the "Click" event in each of them.
    2. In order to access the clipboard, we'll use the Clipboard class introduced in Silverlight 4, which
       supports saving and loading strings in the clipboard. Add the following code to the event handler
       function of the "btnCopy" button to allows saving strings in the clipboard
        C#
        Clipboard.SetText(rtb.Selection.Text);

    3. Find the "Click" event handler function for the "btnPaste" button and add the following code to
       read strings from the clipboard
        C#
        rtb.Selection.Text = Clipboard.GetText();

    4. Next, find the "Click" event handler function for the "btnCut" button and add the following code:
        C#
        Clipboard.SetText(rtb.Selection.Text);
        rtb.Selection.Text = "";

    5. Compile and run the application. Write some text in the rich text area and then press the "Copy"
       button. Open notepad and paste the string (CTRL+V). Return to the application, press the "Create
       New document" button, don't save the document and then press the "Paste" button. The copied
       text will be pasted in the rich text area. The Text Editor application now has clipboard support. Note
       that this support is for text only.
Rich Text Editor



Task 2 – Printing from Silverlight
Silverlight 4 enables developers to use installed printers in order to print application content. In this exercise
we will use this functionality and print the document content.
    1. To print the rich text area, we will use the PrintDocument class introduced in Silverlight 4. Open the
       "MainPage.xaml" file, locate the "btnPrint" button and add a default event handler for the "Click"
       function. Navigate to the event handler function and add the following code:
        C#
        PrintDocument theDoc = new PrintDocument();
        theDoc.DocumentName = "Silverlight 4 Text Editor - Opened Document";
        theDoc.Print();

    2. As you can see, we've called the "Print" method, but we haven't told it what to print. To set the
       printed area, we'll need to handle the PrintDocument.PrintPage event. Add the following code to
       handle the event (place the code before calling the "Print" method)
        C#
        theDoc.PrintPage += (s, args) =>
        {
            args.PageVisual = rtb;
            args.HasMorePages = false;
        };

    3. We'll also add a MessageBox to notify the user the printing was successful. Place the following code
       before calling the "Print" method:
        C#
        theDoc.EndPrint += (s, args) =>
        {
            MessageBox.Show("The document printed successfully", "Text Editor",
                            MessageBoxButton.OK);
        };

    4. Compile and run the application. Enter text and add an image to the rich text area, then press the
       "Print" button. In the printing dialog, select one of the installed printers or print to the "Microsoft
       XPS Document Writer" printer. Save the file and after the printing is finished, open the .xps file -
       examine how the printed content is similar to the content displayed in the rich text control. After
       this task our application has printing features, which allows printing the document.
Rich Text Editor




Exercise 4 – Multilingual Support
Bi-Directional (BiDi) support is new in Silverlight 4 and allows applications to display controls in both left-to-
right flow and in right-to-left (for languages such as Arabic, Persian or Hebrew). Silverlight 4 also supports
Bi-Directional input to allows users to input text written from right to left (for example, Hebrew text).
In this exercise we will learn how to use the application's culture to determine the direction of the controls
and how we can use culture based resources.


Task 1 –BiDi (Bi-Directional) support
Silverlight 4 adds support for BiDi and complex script languages. In this exercise we will add support for
Right-To-Left languages (like Hebrew and Arabic).
    1. Open the "MainPage.xaml" file and look for the "LayoutRoot" Grid control. Notice the
       "FlowDirection" attribute – a new property which belongs to the FrameworkElement class.
       As you can see, the attribute is bound to a property called "IsRTL" which still doesn't exist, so we
       need to create it. Open the "MainPage.xaml.cs" file and add the following dependency property
       code to the class:
        C#
        public bool IsRTL
        {
            get { return (bool)GetValue(IsRTLProperty); }
            set { SetValue(IsRTLProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsRTL.                     This enables
        animation, styling, binding, etc...
        public static readonly DependencyProperty IsRTLProperty =
            DependencyProperty.Register("IsRTL", typeof(bool),
                                        typeof(MainPage),
                                        null);

    2. Next, we'll add a ToggleButton that will be responsible for changing the property's value. Open the
       "MainPage.xaml" file, locate the StackPanel which holds the different action buttons, and add the
       following XAML to the end of the StackPanel, after the "btnImage" button:
        XAML
        <ToggleButton x:Name="btnRTL"
                     Content="{Binding RTL_Button_Caption,
                              Source={StaticResource localizedStrings}}"
                     Checked="btnRTL_Checked" Unchecked="btnRTL_Checked">
        </ToggleButton>
Rich Text Editor



    3. Open the "MainPage.xaml.cs" file and place the event handler function:
        C#
        private void btnRTL_Checked(object sender, RoutedEventArgs e)
        {
            IsRTL = !IsRTL;
        }

    4. Compile and run the application. Enter some text and then press the "LTR" toggle button – The
       entire Grid's content is now right aligned – buttons are aligned to the right, ComboBox content is
       right-aligned and the text entered to the rich text editor flows from the right to the left. Now our
       application is BiDi aware and it takes in account the direction of the text and changes the
       FlowDirection of the layout accordingly.




Task 2 –Culture based UI with Resources
In this task, we'll use 3 cultures – en-US (English), ar-SA (Arabic) and he-IL (Hebrew) and will localize our
application according to the received language setting.
    1. First thing we'll do is decide whether the flow direction of the application should be LTR (left-to-
       right) or RTL (right-to-left), according to the selected culture. Open the file "MainPage.xaml.cs" and
       add the following lines to the constructor:
        C#
        IsRTL =
        Thread.CurrentThread.CurrentUICulture.Parent.Name.ToLower() == "he" ||
        Thread.CurrentThread.CurrentUICulture.Parent.Name.ToLower() == "ar";


    2. In the Solution Explorer, expand the content of the TextEditor.Web project, right-click the
       "SelectCulture.htm" file and select "Set As Start Page".
Rich Text Editor




        Figure 6
        Setting Start Page for Web Application
    3. Double click the "SelectCulture.htm" file to open it. You'll see that the html page is constructed
       from a ComboBox and a Button – pressing the button makes the browser navigate to the Silverlight
       page with the selected culture as part of the URL.
    4. Double click the "TextEditorTestPage.aspx" and look at the culture parameter passed to the
       Silverlight object (bottom of the page). This is how we pass the selected culture from the URL to the
       Silverlight Control.
    5. Compile and run the application. You'll see the following page




        Figure 7
        Language Selection Page in Browser
    6. Select "English" and press the "Open Editor" Button. The application will open it LTR mode.
    7. Run the application again, this time select either "Hebrew" or "Arabic". Notice how the application
       changes its flow to RTL.
    8. Close the application and return to Visual Studio.
    9. In addition to changing flow direction, we also want to change the text that will show in the
       applications tooltips. For that, we'll add the required Resource files for Arabic and Hebrew.
Rich Text Editor



        In the Solution Explorer, right click the TextEditor Project and select Add Existing Item…, navigate
        to the Lab installation folder and from navigate to "\Helpers ", select the two ".resx" files and press
        "Add".
    10. Next, we'll add a header and footer to the page. Open the "MainPage.xaml" file and add the
        following XAML after the RichTextArea element - place the XAML inside the Grid element:
        XAML
        <!--Footer/Status text-->
        <TextBlock x:Name="txtStatus" Grid.Row="3" Margin="2"
                     TextTrimming="WordEllipsis" Foreground="White"
                     Text="{Binding txt_Status_Ready,
                            Source={StaticResource localizedStrings}}"/>
        <!--Header text-->
        <TextBlock x:Name="txtHeader" Grid.Row="0" Margin="2"
                     TextTrimming="WordEllipsis" Foreground="White"
                     Text="{Binding IsRTL,
                     Converter={StaticResource BoolToFlowDirectionConverter}}"/>

    11. Compile and run the application.
    12. Select "Hebrew" and press the "Open Editor" Button. The application will open in RTL mode, and
        you'll see that the header and footer are right-aligned and written in Hebrew. If you move the
        mouse cursor over the buttons in the toolbox, you'll notice the tooltip text is no longer in English.
    13. Repeat step 11 and select "English" to put the application is back to its default state.
    14. Repeat step 11 and select "Arabic". This makes the application right-aligned again. This time the
        text is in Arabic. The application now is fully localized.
Rich Text Editor




Conclusion
In this lab we learned of the new features Silverlight 4 offers in the area of text editing, bi-directional text
and layout, and culture support. We've used the new RichTextArea control that can contain rich text
content This allows the user to input rich text and embed hyperlinks and images into a document and to
save or print the rich text.
We've also seen the Clipboard capabilities of Silverlight 4 and how we can Copy & Paste text in and out of
Silverlight. In addition, we've used Silverlight 4’s new bi-directional (BiDi) feature that allows us to change
the flow direction of our Silverlight applications to either left-to-right (LTR) or right-to-left (RTL). This
enables our application to support input and output to languages such as Arabic, Persian or Hebrew. We've
also seen how to use this feature with a Resource file to display different strings in accordance with the
Culture selected by the user.

								
To top