Search
Thursday, November 20, 2008 ..:: Blendblog.net ::.. Register  Login
 Bloggers Minimize

 Print   
 Sponsors Minimize

 Print   
 Users Online Minimize
Membership Membership:
Latest New User Latest: areel
New Today New Today: 0
New Yesterday New Yesterday: 0
User Count Overall: 15

People Online People Online:
Visitors Visitors: 0
Members Members: 0
Total Total: 0

Online Now Online Now:

 Print   
 Welcome to blendblog.net! Minimize

If you are a developer or designer who is creating cutting edge user interface experiences using Microsoft Expression Blend you've just found a great resource!  The purpose of this site is to share our experience with this brand new product.  As with any new piece of software there is a ton to discover.  Bugs will be revealed and workarounds discovered, hopefully this can be a resource to share in the discovery process!

While this site will focus largely on Expression Blend, it will also encompass WPF, Visual Studio, Silverlight, and other .net 3.5 technologies as they relate to the creation of great software.

Please login using your Microsoft LiveID or register a new account.  Doing so will let you comment on any of the blog entries on the site.  We look forward to helping you in your endeavors as well as you helping others in theirs!  We'd love to have more bloggers on our site...if you are interested please register and contact us!


 Print   
 WPF RichTextBox may offer impressive features, but seems to lack features readily available from prior RichEdit-based RichTextBox Minimize
Location: BlogsRob Tuch    
Posted by: RobTuch 1/8/2008 1:54 PM

 

 

I was excited at the prospect of building an editor around the new WPF RichTextBox, which Microsoft lists as the functional equivalent of the WinForms RichTextBox (see http://msdn2.microsoft.com/en-us/library/ms750559.aspx).  This RichTextBox  should finally permit insertion of dazzling media elements and flexible layouts...

 

However, there are some implementation snags.  For example, many of the formatting functions that were previously available by a simple call to a (WinForms) RichEdit-based RichTextBox property, now require implmentation of an equivalent property.  For example a SelColor property that changes the text color:

 

        Public Property SelColor() As Color

            Dim oCurrentColor As SolidColorBrush

            Get

                ' Get current foreground text color

                Try

                    oCurrentColor = WPFRichTextBox.Selection.GetPropertyValue(Inline.ForegroundProperty)

                Catch

                    oCurrentColor = WPFRichTextBox.Foreground

                End Try

                SelColor = oCurrentColor.Color

            End Get

            Set(ByVal value As Color)

                ' Get current fore color and convert to System.Drawing.Color

                WPFRichTextBox.Selection.ApplyPropertyValue(Inline.ForegroundProperty, New SolidColorBrush(Color.FromRgb(value.R, value.G, value.B)))

            End Set

        End Property

 

This is a relatively simple property to implement, but others require further code for error and text context checking.

   

Also, although the WPF RichTextBox supports RTF text, it seems to be a subset of that supported by the RichEdit-based RichTextBox.  For example the \protect (for protected text) and \v (for hidden text) are ignored.  There are some workarounds for this (for example on could uniquely color-code the protected text and use a practically-invisible fontsize for the hidden text), but these require additional event handlers (to prevent edit when cursor is on protected text, to skip over the "invisible" characters, and convert the XAML to/from corrected RTF as needed).  It would be great to learn that these standard RichEdit RTF features will just be available in future version of the WPF RichTextBox.

 

In addition, although Spell-checking is available as a built-in feature, it is currently limited to Western languages, without support for custom dictionaries.  It has been suggested that Microsoft will allow for custom dictionaries and expanded language support in the (hopefull very) near future.

 

The WPF RichTextBox poses a another challenge in that the underlying XAML of selected content is not readily availalable with all content intact--any UI elements added are converted to a textual equivalent (e.g., <InlineUIContainer>..</InlineUIContainer> elements that contain UI elements convert to a <run></run>).  This poses a difficulty when one expects to support drag/drop or cut/paste with the enhanced UI elements as well as text.  So far, a workaround has been to handle the drag/drop (via WPFRichTextBox_PreviewMouseMove and WPFRichTextBox_PreviewDrop events respectively) or cut/paste operations (via WPFRichTextBox_PreviewKeyDown event) so that any replaced UI elements can be restored to the original content prior to completion of the Drop or Paste.  For now, it seems this can be accompished using the XAMLWriter with code similar to the following...

    Private Function GetTextRangeXAML(ByVal objTextRange As TextRange) As String
        ' Traverse elements convered by current range and construct XAML

        Dim objParagraph As Paragraph
        Dim objTextElement As TextElement
        Dim objInline As Inline
        Dim strXAML As String
        Dim strSectionStart As String
        Dim objSection As New Section
        Dim booStart As Boolean
        Dim objSelectionText As String
        Dim objTR As TextRange

        ' Get paragraph of start position
        objParagraph = objTextRange.Start.Paragraph
        booStart = True

        objTextElement = objTextRange.Start.Parent
        If objTextElement.GetType.Name = "Paragraph" Then
            ' Started at paragraph, so set 1st Inline to 1st Inline of Paragraph
            objInline = objParagraph.Inlines.FirstInline
        Else
            objInline = objTextElement
        End If

        Do While Not objParagraph Is Nothing
            strXAML = strXAML & "<Paragraph>"
            ' handle inline elements within the paragraph
            Do While Not objInline Is Nothing
                Dim objMemoryStream As New MemoryStream()
                Dim objStreamReader As New StreamReader(objMemoryStream)
                Select Case objInline.GetType.Name
                    Case "Run"
                        If booStart Then
                            ' Get content in run offset from start position
                            booStart = False
                            objTR = New TextRange(objTextRange.Start, objInline.ElementEnd)
                            objTR.Save(objMemoryStream, DataFormats.Xaml)
                            objMemoryStream.Position = 0
                            objSelectionText = objStreamReader.ReadToEnd()
                            'objSelectionText = "<Run>" & objTR.Text & "</Run>"
                            strXAML = strXAML & objSelectionText
                        Else
                            ' Get full run xaml
                            objTR = New TextRange(objInline.ElementStart, objInline.ElementEnd)
                            objTR.Save(objMemoryStream, DataFormats.Xaml)
                            objMemoryStream.Position = 0
                            objSelectionText = objStreamReader.ReadToEnd()
                            'objSelectionText = "<Run>" & objTR.Text & "</Run>"
                            strXAML = strXAML & objSelectionText
                        End If
                    Case "InlineUIContainer"
                        ' Get XAML for object
                        strXAML = strXAML & XamlWriter.Save(objInline)
                    Case Else
                End Select
                objInline = objInline.NextInline
            Loop
            ' Next paragraph
            strXAML = strXAML & "</Paragraph>"
            objParagraph = objParagraph.NextBlock
            If Not objParagraph Is Nothing Then
                objInline = objParagraph.Inlines.FirstInline
            End If
        Loop

        strSectionStart = XamlWriter.Save(objSection)
        strSectionStart = strSectionStart.Substring(0, strSectionStart.IndexOf("/>")) & ">"
        strXAML = strSectionStart & strXAML & "</Section>"

        Return strXAML
    End Function

Permalink |  Trackback

Your name:
Title:
Comment:
Add Comment   Cancel 

  
 Search Minimize

 Print   
 Archive Minimize

 Print   
 Blendblog Survey Minimize
Our next client application will be written using:




Submit Survey  View Results

 Print   
Copyright 2008 by blendblog.net   Terms Of Use  Privacy Statement
DotNetNuke® is copyright 2002-2008 by DotNetNuke Corporation