Introduction
This control allows the user to quickly and easily databind an object to the Rtf
property of a RichTextBox
control.
Background
At work, I lead a team that has the task of converting our Microsoft Access 2003 application into a .NET app with a SQL 2005 backend database. Our program uses RTF
formatted strings in too many places to count... Invoices, time cards, notes, appointments, document notes, project tasks, etc.
In Microsoft Access, we used a 3rd party ActiveX library called Total Access Memo, which was amazing for what we wanted to do. But in .NET, Microsoft was nice enough to give us the RichTextBox
control. The only problem was the fact that they did not give us the ability to easily bind data to the Rtf
property of the control!
So after using a completely hacked, round-a-bout method of binding the data, I asked myself 'What is the point of a RichTextBox
that cannot bind to the rich text?' This question pestered me enough to where I had to fix it.
Using the Code
This control can be utilized just like the default RichTextBox
. The only difference is that you now have an additional property called Rtf
that is available under the '(Databindings)
' category in the designer's PropertyGrid
.
The dbRTBox
class inherits System.Windows.Forms.RichTextBox
class, and hides the Rtf
property with a new one.
The code is surprisingly simple:
C#
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace DataboundRTB
{
[ClassInterface(ClassInterfaceType.AutoDispatch), DefaultBindingProperty("Rtf"),
Description("DescriptionRichTextBox"), ComVisible(true),
Docking(DockingBehavior.Ask),
Designer("System.Windows.Forms.Design.RichTextBoxDesigner,
System.Design, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a")]
class dbRTBox : System.Windows.Forms.RichTextBox
{
[Bindable(true), RefreshProperties(RefreshProperties.All),
SettingsBindable(true), DefaultValue(""), Category("Appearance")]
new public string Rtf
{
get
{
return base.Rtf;
}
set
{
base.Rtf = value;
}
}
}
}
VB
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
<ClassInterface(ClassInterfaceType.AutoDispatch), _
DefaultBindingProperty("Rtf"), Description("DescriptionRichTextBox"), _
ComVisible(True), Docking(DockingBehavior.Ask), _
Designer("System.Windows.Forms.Design.RichTextBoxDesigner, _
System.Design, Version=4.0.0.0, Culture=neutral, _
PublicKeyToken=b03f5f7f11d50a3a")> _
Public Class dbRTBox
Inherits RichTextBox
<Bindable(True), RefreshProperties(RefreshProperties.All), _
SettingsBindable(True), DefaultValue(""), Category("Appearance")> _
Public Overloads Property Rtf As String
Get
Return MyBase.Rtf
End Get
Set(ByVal value As String)
MyBase.Rtf = value
End Set
End Property
End Class
As you can see, the class has one property (Rtf
) that hides the base
.Rtf
property. We did this just so we can put the tags above the property to let the designer know that we want to allow databinding on this property.
The code...
Bindable(true)
...is the key line of code that makes this all work. This tag tells the designer that you want to bind to this property.
Since we will almost always want to bind to the Rtf
property, we also want to add a tag to the class...
C#
[ClassInterface(ClassInterfaceType.AutoDispatch),
DefaultBindingProperty("Rtf"), Description("DescriptionRichTextBox"),
ComVisible(true), Docking(DockingBehavior.Ask),
Designer("System.Windows.Forms.Design.RichTextBoxDesigner,
System.Design, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a")]
VB
<ClassInterface(ClassInterfaceType.AutoDispatch),
DefaultBindingProperty("Rtf"), Description("DescriptionRichTextBox"),
ComVisible(True), Docking(DockingBehavior.Ask),
Designer("System.Windows.Forms.Design.RichTextBoxDesigner,
System.Design, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a")> _
In this tag, we utilize the default RichTextBox
tags, but we add the tag DefaultBindingProperty("Rtf")
, so when we drag a field from the DataSources
window onto the dbRTBox
control, it will bind directly to the Rtf
property, rather than the Text
property.
In the sample code, Form1
has a sub class called DataItem
.
public class DataItem
{
public DataItem(int i)
{
using (RichTextBox rtb = new RichTextBox())
{
rtb.Text = "Item #" + i.ToString();
Key = rtb.Rtf;
}
Value = i;
}
public string Key { get; set; }
public int Value { get; set; }
}
In this class, you can see in the constructor we simply create an RTF formatted string (using a RichTextbox
:-D ) that simply contains the Item Number of the current item, and store it into the Key
property.
The constructor of Form1
simply loads a List<DataItem>
that contains 20 items into the Form1_DataItemBindingSource
. Using the 'Next' and 'Prev' buttons on the form, you can navigate through the items in the binding source and see that the actual items are bound to the Rtf
property of the control, not the Text
property.
Points of Interest
The best part of this control (other than its simplicity) is that you can perform your databinding from within the WinForms designer, so even the most inexperienced programmer can easily databind rich text fields in just moments using nothing but the mouse.
History
- Created 6/24/2010
- Updated 6/24/2010 to include VB code