Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Persisting Rich Text

0.00/5 (No votes)
3 Mar 2006 2  
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.

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.

[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.

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:

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