Click here to Skip to main content
16,018,904 members
Articles / Desktop Programming / Windows Forms
Article

Persisting Rich Text

Rate me:
Please Sign up or sign in to vote.
4.69/5 (16 votes)
3 Mar 20064 min read 153.8K   2.4K   83   36
Extending the RichTextBox to support form persistance and data binding.

Note: This control is totally standalone. If you've downloaded it before, please do again as I accidenly left some third party references in the demo project.

Introduction

This article was prompted by comments about Rich Parson's RichTextBoxExtended Control. This is a very useful control that includes a tool bar to augment the existing RichTextBox control into a word processor.

Image 1

The comments from users were very positive, but there was a desire to be able to set the content of a rich text control via the Rtf property so it can be persisted in the form design. Secondly, for cases where the content is being edited at runtime, it makes sense to be able to data bind to the Rtf property. This article explains how to do both of these so you can build fully functional Rich Text forms with a minimum of effort.

Minor Changes

I made a few minor changes unconnected with persistence that I hope won't be controversial.

  • I changed the namespace so it has a different name from the control, as this will cause problems with the latest version of C#.
  • I added DefaultValue attributes to all the properties so they don't show up bold unless changed.
  • I introduced a number of additional properties which are self explanatory, such as ToolBarVisible, EditorBackColor, and BorderStyle.
  • I've commented out the properties, allowing direct access to the internal RichText and ToolBar controls, as this breaks the encapsulation, and providing alternative methods for setting the same property is confusing and can cause persistence issues.

Gotyas

When working with the existing RichTextBox control, there are two "features" that can catch you out. Firstly, as mentioned by Rich, if you set Rtf before the form initialization, the RichTextBox control will sometimes lose its formatting and just display plain text. Secondly, there is a bug in the Rtf property where it sometimes returns a null character as the very last character in the string. This causes no problems with designer form persistence when the RichTextBox control has a short content. However, once the content gets longer, the designer serialization code has a nervous breakdown and messes up the job of breaking the string into multiple lines. (Possibly, this is why MS made the Rtf property unavailable as standard in the property editor in Visual Studio.) This caused me more than a little bit of grief but it needn't cause you any if you use the RichTextBoxExtended included with this article.

How to get the Rtf property to work

In order for consumers of the Rtf property to be aware of changes, there needs to be a property change event called RtfChanged. This event will automatically be hooked to handle data binding or form designer serialization.

We must ensure that this event is triggered whenever the content has been updated. The obvious case is when the user has updated the content directly. This, we check in a Leave event handler. The Rtf property may be set directly so we need to trigger our event here also. Finally, Rtf could change indirectly as a result of a change to the Text property.

C#
[Category("Property Changed")]
public event EventHandler RtfChanged;

[
    System.ComponentModel.Description("Contents in Rtf format"),
    RecommendedAsConfigurable(true),
    Category("Data"),
    Bindable(true),
    Editor(typeof(Design.RichTextBoxExtendedEditor), 
           typeof(System.Drawing.Design.UITypeEditor))
]
public string Rtf
{
    get
    {    return rtb1.Rtf;
    }
    set
    {    rtb1.Rtf= value;
        if (RtfChanged!=null)
            RtfChanged(this,EventArgs.Empty);
    }
}
#endregion

private void rtb1_TextChanged(object sender, System.EventArgs e)
{
    if (RtfChanged!=null)
        RtfChanged(this,EventArgs.Empty);
}

private void rtb1_Leave(object sender, System.EventArgs e)
{
    if (this.rtb1.Modified && RtfChanged!=null)
        RtfChanged(this,EventArgs.Empty);
}

Providing a Property Editor for the Rtf Property

There's a pleasing recursion here, as the ExtendedRichText control is used to edit its own Rtf property.

Image 2

Implementing a property editor is accomplished by adding the Editor attribute to the Rtf property. This attribute specifies which UITypeEditor to invoke. The implementation of this UITypeEditor is fairly simple as shown below:

C#
class RichTextBoxExtendedRtfEditor:System.Drawing.Design.UITypeEditor
{
    public override System.Drawing.Design.UITypeEditorEditStyle 
                    GetEditStyle(ITypeDescriptorContext context)
    {
        if (context==null)
            return base.GetEditStyle(null);
        return System.Drawing.Design.UITypeEditorEditStyle.Modal;
    }

    public override object EditValue(ITypeDescriptorContext context, 
                           IServiceProvider provider, object value)
    {
        if (context!=null && provider!=null)
        {
            IWindowsFormsEditorService edSrv= 
              (IWindowsFormsEditorService)
              provider.GetService(typeof(IWindowsFormsEditorService));
            if (edSrv!=null)
            {
                RichTextBoxExtendedRtfEditorForm dialog= 
                  new RichTextBoxExtendedRtfEditorForm();
                if (value is String)
                    dialog.Value= (string)value;    
                if (edSrv.ShowDialog(dialog)==
                         System.Windows.Forms.DialogResult.OK)
                    value= dialog.Value;
                dialog.Dispose();
                dialog= null;
            }
        }
        return value;
    }
}

Data Binding and Automatic Binding

Once persistence of Rtf has been implemented for designer serialization, it will automatically work for data binding. The image of the included demo application shows two RichTextExtended controls - one is read only and is persisted in the form design. The other is editable and is data bound and persisted in a DataSet at runtime. To keep the sample simple to install, this DataSet is persisted in a text file as XML. In a real world application, persistence would probably be to a database and it works fine this way. Just make sure your database columns are large enough as the formatting information makes rich text bigger than you might expect.

A standalone solution (RichTextExtended.sln) has been provided in the demo project. If you use AgileStudio, a solution has also been included (RichTextBoxExtended2.sln) that implements automatic binding. In fact, I used this mechanism to knock together the demo app really quickly.

Conclusion

This modified RichTextBoxExtended now has a property editor to allow you to persist Rich Text as part of the form design. It also supports data binding to allow the editing of Rich Text from a data source at runtime. Now, you can knock together rich text apps without having to hand code your Rtf assignments.

However, if you want to go one step further, the automatic binding in AgileStudio makes it really fly as this automatically builds the SQL Server database and builds the stored procedures, typed datasets, and bindings when you just drop the ExtendedRichText control on the form.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Ireland Ireland
Declan Brennan is Chief Architect for Sekos Technology (www.sekos.com). Over the years he has worked in a huge range of technologies and environments and still gets a great thrill from the magic of computers.

Comments and Discussions

 
QuestionHow to set rtf data? Pin
gafferuk27-Aug-06 3:08
gafferuk27-Aug-06 3:08 
AnswerRe: How to set rtf data? Pin
gafferuk27-Aug-06 7:09
gafferuk27-Aug-06 7:09 
GeneralRTF datatype Pin
cookie king1-Aug-06 5:24
cookie king1-Aug-06 5:24 
QuestionCan we edit .MHTML content in rich text box control? Pin
Pham Dinh Truong31-Jul-06 0:22
professionalPham Dinh Truong31-Jul-06 0:22 
GeneralToolbar becomes invisible Pin
bdSGIIMS9-Jun-06 9:36
bdSGIIMS9-Jun-06 9:36 
GeneralTrying to use but something is weird Pin
bdSGIIMS7-Jun-06 17:27
bdSGIIMS7-Jun-06 17:27 
Generalwhy RtfChanged event - answer... Pin
qwerty@sh2-Jun-06 19:07
qwerty@sh2-Jun-06 19:07 
GeneralMinor Problem Pin
Tailslide22-Mar-06 10:35
Tailslide22-Mar-06 10:35 
Hi this is a great control and has saved me a ton of work, thank you!
I'm using it with VS2005 and I have run into one small problem.

The databound value is not saved to the dataset until the user tabs out of the control. If you click the close button on a window and then try to save the record in the closing event the dataset does not have the value. Other databound controls do not behave this way and it create a bit of a problem.

You can't just copy over the values to your dataset because even if the values are identical I think this causes the row to be flagged as updated. Plus you need to check for null and so on. The result is that I'm using the databinding for reading but manually put the values back into the dataset with code.

I'm up against a deadline so I can't investigate further but I thought I'd mention it. Who knows, maybe the control is fine and I'm just doing something wrong.

GeneralQuestion about databindings Pin
SebaSuper7-Mar-06 9:27
SebaSuper7-Mar-06 9:27 
GeneralRe: Question about databindings Pin
Declan Brennan7-Mar-06 22:04
Declan Brennan7-Mar-06 22:04 
GeneralMissing needed components! Pin
rareJuliet1-Mar-06 8:18
rareJuliet1-Mar-06 8:18 
GeneralRe: Missing needed components! Pin
Declan Brennan1-Mar-06 9:56
Declan Brennan1-Mar-06 9:56 
GeneralBig thanks Pin
Almatrodi20-Feb-06 4:38
Almatrodi20-Feb-06 4:38 
GeneralRe: Big thanks Pin
Declan Brennan21-Feb-06 1:58
Declan Brennan21-Feb-06 1:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.