Click here to Skip to main content
13,300,654 members (54,529 online)
Click here to Skip to main content
Add your own
alternative version


150 bookmarked
Posted 18 Dec 2008

RichTextBox Cell in a DataGridView

, 9 Jul 2014
Rate this:
Please Sign up or sign in to vote.
Source code for how to create a RichTextBox column in a DataGridView



You can use this DataGridViewRichTextBoxColumn to display and edit RTF content.


A customer wanted to have superscript and subscript support in his reports, and he also wanted to edit the reports. I thought RTF files were a good choice. Then, a problem came up. I needed a setting dialog with a DataGridView, where the user will input text (should support superscript and subscript). So, I decided to put a RichTextBox in the DataGridView.

I found an idea here. There was no source code. So, I decided to write about it and post my first article in CodeProject.

Three Classes to make a DataGridViewColumn

There is an example of a calendar DataGridViewColumn here.

To make a custom DataGridViewColumn, we should write three classes:

  1. An editor control class derived from IDataGridViewEditingControl
  2. A cell class derived from DataGridViewCell or its descendant class
  3. A column class derived from DataGridViewColumn or its descendant class

First, the Editor Control Class

Here is the code for supporting multiline input in the RichTextBox:

public class  DataGridViewRichTextBoxEditingControl : 
        RichTextBox, IDataGridViewEditingControl
    // To implement multiline, 'Enter' should be treated as an input key.
    protected override bool IsInputKey(Keys keyData)
        Keys keys = keyData & Keys.KeyCode;

        if (keys == Keys.Return)
            return this.Multiline;

        return base.IsInputKey(keyData);

    // Tell DataGridView 'Enter' is an input key to this control.
    // And some other keys are also input keys.
    public bool EditingControlWantsInputKey
    (Keys keyData, bool dataGridViewWantsInputKey)
        switch ((keyData & Keys.KeyCode))
            case Keys.Return:
                // The code for 'Enter' is copied from 
                // DataGridViewTextBoxEditingControl,
                // Shift + Enter = NewLine
                if ((((keyData & (Keys.Alt | Keys.Control | Keys.Shift))
                     == Keys.Shift) && this.Multiline))
                    return true;
            case Keys.Left:
            case Keys.Right:
            case Keys.Up:
            case Keys.Down:
                return true;

        return !dataGridViewWantsInputKey;

Here is the code for shortcuts. RichTextBox already supports Ctrl + '+' and Ctrl + Shift + '+' for subscript and superscript. What needs to be done is add support for Ctrl + 'B', Ctrl + 'I', and Ctrl + 'U'.

protected override void OnKeyDown(KeyEventArgs e)

    if (e.Control)
        switch (e.KeyCode)
            // Control + B = Bold
            case Keys.B:
                if (this.SelectionFont.Bold)
                    this.SelectionFont = new Font(this.Font.FontFamily, 
                     this.Font.Size, ~FontStyle.Bold & this.Font.Style);
                    this.SelectionFont = new Font(this.Font.FontFamily, 
                     this.Font.Size, FontStyle.Bold | this.Font.Style);
            // Control + U = Underline
            case Keys.U:
                if (this.SelectionFont.Underline)
                    this.SelectionFont = new Font(this.Font.FontFamily, 
                     this.Font.Size, ~FontStyle.Underline & this.Font.Style);
                    this.SelectionFont = new Font(this.Font.FontFamily, 
                     this.Font.Size, FontStyle.Underline | this.Font.Style);
            // Control + I = Italic
            // Conflicts with the default shortcut
            //case Keys.I:
            //    if (this.SelectionFont.Italic)
            //    {
            //        this.SelectionFont = new Font(this.Font.FontFamily, 
            //         this.Font.Size, ~FontStyle.Italic & this.Font.Style);
            //    }
            //    else
            //        this.SelectionFont = new Font(this.Font.FontFamily, 
            //         this.Font.Size, FontStyle.Italic | this.Font.Style);
            //    break;

Second, the Cell Class

This is the most important class for RichTextBoxColumn, because here we do the painting job for the cell.

I suggest you should first take a look here. Then, you will know how to print a RichTextBox. I just changed it a little to print it to an Image object.

The cell class was derived from DataGridViewTextBoxCell due to speed problems. I changed it with DataGridViewImageCell. I needed to do something to avoid errors in the DataGridViewImageCell.

public class DataGridViewRichTextBoxCell : DataGridViewImageCell
    // The value should be RTF string, so these types should be changed.	
    public override Type ValueType
            return typeof(string);
            base.ValueType = value;

    public override Type FormattedValueType
            return typeof(string);

    // Since the value type is changed, we need to do something more.
    private static void SetRichTextBoxText(RichTextBox ctl, string text)
            ctl.Rtf = text;
        catch (ArgumentException)
            ctl.Text = text;
    public override void InitializeEditingControl
	(int rowIndex, object initialFormattedValue, 
	DataGridViewCellStyle dataGridViewCellStyle)
	(rowIndex, initialFormattedValue, dataGridViewCellStyle);

        RichTextBox ctl = DataGridView.EditingControl as RichTextBox;

        if (ctl != null)
            SetRichTextBoxText(ctl, Convert.ToString(initialFormattedValue));

    protected override object GetFormattedValue
	(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, 
	    TypeConverter valueTypeConverter, 
		TypeConverter formattedValueTypeConverter,
		 DataGridViewDataErrorContexts context)
        return value;

Now, we will paint the cell.

The RichTextBoxPrinter.Print function is from the link I mentioned above.

private static readonly RichTextBox _editingControl = new RichTextBox();

// Images for selected and normal states.
private Image GetRtfImage(int rowIndex, object value, bool selected)
    Size cellSize = GetSize(rowIndex);

    if (cellSize.Width < 1 || cellSize.Height < 1)
        return null;

    RichTextBox ctl = null;

    if (ctl == null)
        ctl = _editingControl;
        ctl.Size = GetSize(rowIndex);
        SetRichTextBoxText(ctl, Convert.ToString(value));

    if (ctl != null)
        // Print the content of RichTextBox to an image.
        Size imgSize = new Size(cellSize.Width - 1, cellSize.Height - 1);
        Image rtfImg = null;

        if (selected)
            // Selected cell state
            ctl.BackColor = DataGridView.DefaultCellStyle.SelectionBackColor;
            ctl.ForeColor = DataGridView.DefaultCellStyle.SelectionForeColor;

            // Print image
            rtfImg = RichTextBoxPrinter.Print(ctl, imgSize.Width, imgSize.Height);

            // Restore RichTextBox
            ctl.BackColor = DataGridView.DefaultCellStyle.BackColor;
            ctl.ForeColor = DataGridView.DefaultCellStyle.ForeColor;
            rtfImg = RichTextBoxPrinter.Print(ctl, imgSize.Width, imgSize.Height);

        return rtfImg;

    return null;

// Draw the image of the rich text box
protected override void Paint(Graphics graphics, 
	Rectangle clipBounds, Rectangle cellBounds, int rowIndex, 
    DataGridViewElementStates cellState, object value, 
	object formattedValue, string errorText, 
    	DataGridViewCellStyle cellStyle, 
	DataGridViewAdvancedBorderStyle advancedBorderStyle, 
	DataGridViewPaintParts paintParts)
    base.Paint(graphics, clipBounds, cellBounds, rowIndex, 
	cellState, null, null, errorText, cellStyle, advancedBorderStyle, paintParts);

    Image img = GetRtfImage(rowIndex, value, base.Selected);

    if (img != null)
        graphics.DrawImage(img, cellBounds.Left, cellBounds.Top);

Other things required for cell edit:

// Remember, DataGridViewImageCell doesn't behave like DataGridViewTextBoxCell.
// So we need to handle the mouse events for edit.

#region Handlers of edit events, copied from DataGridViewTextBoxCell 

private byte flagsState;

protected override void OnEnter(int rowIndex, bool throughMouseClick)
    base.OnEnter(rowIndex, throughMouseClick);

    if ((base.DataGridView != null) && throughMouseClick)
        this.flagsState = (byte)(this.flagsState | 1);

protected override void OnLeave(int rowIndex, bool throughMouseClick)
    base.OnLeave(rowIndex, throughMouseClick);

    if (base.DataGridView != null)
        this.flagsState = (byte)(this.flagsState & -2);

protected override void OnMouseClick(DataGridViewCellMouseEventArgs e)
    if (base.DataGridView != null)
        Point currentCellAddress = base.DataGridView.CurrentCellAddress;

        if (((currentCellAddress.X == e.ColumnIndex) && 
            (currentCellAddress.Y == e.RowIndex)) && 
            (e.Button == MouseButtons.Left))
            if ((this.flagsState & 1) != 0)
                this.flagsState = (byte)(this.flagsState & -2);
            else if (base.DataGridView.EditMode != 


Finally, the Column Class

It's easy because we already have the classes for the editor control and the cell:

public class DataGridViewRichTextBoxColumn : DataGridViewColumn
    public DataGridViewRichTextBoxColumn()
        : base(new DataGridViewRichTextBoxCell())

    public override DataGridViewCell CellTemplate
            return base.CellTemplate;
            if (!(value is DataGridViewRichTextBoxCell))
                throw new InvalidCastException("CellTemplate must" + 
                      " be a DataGridViewRichTextBoxCell");

            base.CellTemplate = value;

Using the Code

Use it just like other columns for DataGridView. See the demo source code.

Points of Interest

At first, the cell class was derived from DataGridViewTextBoxCell. It's OK if the text is short. But, when the RTF content was long or it contained a picture, it became slow when entering or leaving the cell. Then, I changed the parent class to DataGridViewImageCell, and now the speed is no longer a problem.


  • 7/19/2014
    • Add some sample code for ashsanD to demostrate how to set the specific text bold. E.g. user can search some text in the datagridview and the matched text will be highlighted.
  • 4/30/2009
    • Updated class DataGridViewRichTextBoxCell (including gzobi666's correction)
    • Updated RichTextBoxPrinter according to the D_Kondrad's correction
  • 12/18/2008
    • Added the code with instructions


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer
China China
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionAuto Resizing Pin
Sten Miles15-Nov-16 9:15
memberSten Miles15-Nov-16 9:15 
QuestionMulti-Line Pin
Member 1264304119-Jul-16 6:01
memberMember 1264304119-Jul-16 6:01 
QuestionPaint is not working Pin
Mehdi Azizi2-Jan-15 14:16
memberMehdi Azizi2-Jan-15 14:16 
QuestionAutoSizeRowsMode and WrapMode Pin
rmackenzie30-Dec-14 23:17
memberrmackenzie30-Dec-14 23:17 
AnswerRe: AutoSizeRowsMode and WrapMode Pin
Member 1111129712-Jan-15 4:25
memberMember 1111129712-Jan-15 4:25 
AnswerRe: AutoSizeRowsMode and WrapMode Pin
Member 115356093-Jun-16 5:16
memberMember 115356093-Jun-16 5:16 
GeneralRe: AutoSizeRowsMode and WrapMode Pin
gowthamkg29-Mar-17 0:18
membergowthamkg29-Mar-17 0:18 
QuestionProblem with dataGridView1_CellEnter Pin
Member 1091247419-Jul-14 4:22
memberMember 1091247419-Jul-14 4:22 
AnswerRe: Problem with dataGridView1_CellEnter Pin
Member 1091247431-Jul-14 2:27
memberMember 1091247431-Jul-14 2:27 
QuestionLabel text not shown completely. Pin
leiyangge19-Jul-14 3:27
memberleiyangge19-Jul-14 3:27 
QuestionSystem.argumentoutofrange exception:index was out of range Pin
Member 1091247418-Jul-14 8:13
memberMember 1091247418-Jul-14 8:13 
AnswerRe: System.argumentoutofrange exception:index was out of range Pin
Member 1091247419-Jul-14 1:36
memberMember 1091247419-Jul-14 1:36 
QuestionProblem with lternatingRowsDefaultCellStyle and MiddleCenter Pin
Member 1091247418-Jul-14 2:57
memberMember 1091247418-Jul-14 2:57 
AnswerRe: Problem with lternatingRowsDefaultCellStyle and MiddleCenter Pin
Member 1091247421-Jul-14 9:50
memberMember 1091247421-Jul-14 9:50 
GeneralRe: Problem with lternatingRowsDefaultCellStyle and MiddleCenter Pin
Member 1091247422-Jul-14 9:58
memberMember 1091247422-Jul-14 9:58 
Questionhow to highlight search term Pin
ashsanD16-Sep-13 20:26
memberashsanD16-Sep-13 20:26 
AnswerRe: how to highlight search term Pin
mrwisdom8-Jul-14 18:05
membermrwisdom8-Jul-14 18:05 
GeneralRe: how to highlight search term Pin
ashsanD10-Nov-15 21:03
memberashsanD10-Nov-15 21:03 
Questionis it available in vb Pin
ashsanD12-Sep-13 0:36
memberashsanD12-Sep-13 0:36 
AnswerRe: is it available in vb Pin
Rick Hirons22-Nov-13 2:00
memberRick Hirons22-Nov-13 2:00 
GeneralRe: is it available in vb Pin
ashsanD10-Nov-15 21:05
memberashsanD10-Nov-15 21:05 
GeneralRe: is it available in vb Pin
Member 125622159-Jun-16 6:26
memberMember 125622159-Jun-16 6:26 
QuestionHi! Could I ask you a related question? Pin
Member 81065404-Jun-13 22:26
memberMember 81065404-Jun-13 22:26 
AnswerRe: Hi! Could I ask you a related question? Pin
mrwisdom5-Jun-13 18:29
membermrwisdom5-Jun-13 18:29 
GeneralMy vote of 5 Pin
Mazen el Senih29-Mar-13 6:00
memberMazen el Senih29-Mar-13 6:00 
QuestionChange font Pin
vyh15-Dec-12 14:17
membervyh15-Dec-12 14:17 
QuestionSlow Perfomance Pin
andrea tosetto14-Dec-12 1:49
memberandrea tosetto14-Dec-12 1:49 
SuggestionRe: Slow Perfomance Pin
Member 814490724-Jan-13 22:48
memberMember 814490724-Jan-13 22:48 
GeneralRe: Slow Perfomance Pin
mrwisdom5-Jun-13 18:28
membermrwisdom5-Jun-13 18:28 
GeneralRe: Slow Perfomance Pin
Member 878169726-Nov-14 6:40
memberMember 878169726-Nov-14 6:40 
QuestionArtifacts/rogue pixels when using Segoe UI font (and some padding) Pin
TheMperor4-Oct-12 23:21
memberTheMperor4-Oct-12 23:21 
QuestionHow to add columns dinamically? Pin
Thiago_Lima19-Sep-12 9:29
memberThiago_Lima19-Sep-12 9:29 
AnswerRe: How to add columns dinamically? Pin
TheMperor4-Oct-12 23:03
memberTheMperor4-Oct-12 23:03 
QuestionAutoResizeRows Pin
Member 87627483-Apr-12 2:38
memberMember 87627483-Apr-12 2:38 
GeneralMy vote of 5 Pin
A.J.Wegierski1-Apr-12 20:22
memberA.J.Wegierski1-Apr-12 20:22 
GeneralMy vote of 5 Pin
ProEnggSoft22-Mar-12 15:39
memberProEnggSoft22-Mar-12 15:39 
QuestionRight click copy Pin
jimdunntx30-Jan-12 7:36
memberjimdunntx30-Jan-12 7:36 
QuestionPrinting Pin
Member 298050924-Jan-12 3:50
memberMember 298050924-Jan-12 3:50 
QuestionToolkit issue? Pin
bioshock1720-Jan-12 7:14
memberbioshock1720-Jan-12 7:14 
GeneralDataGridView.AutoSizeRows (other solution) Pin
Member 38656237-Nov-11 8:21
memberMember 38656237-Nov-11 8:21 
QuestionParent Window Re: DataGridView.AutoSizeRows (other solution) Pin
Arne Christian Rosenfeldt18-Jan-13 10:42
memberArne Christian Rosenfeldt18-Jan-13 10:42 
I need word wrap in the control.
Thus I tried code like[VB version]
Which contains most importantly:
Private Const WM_USER = &H400
Private Const WM_NOTIFY = &H4E
Private Const ENM_REQUESTRESIZE As Long = &H40000
Private Const EN_REQUESTRESIZE = &H701
Public Const EM_REQUESTRESIZE = (WM_USER + 65)

For this to work I need the parent window of the RichTextbox.
But I cannot find the official parent window in the documentation.
I could use the debugger and find the window on my chosen .NET version and OS version.
But still then, I find the hook into its WinProc (as mentioned in the link above) a bit over the top.

Why does the DataGridView place an obscure Window between itself and the hosted control?
This window has the size of the Cell, but class Cell does not give me a Handle to it.
Or is this window used by .NET to implement[^]
? And I should just subscribe to the event?

I am planning to
override GetPreferredSize

as suggested in this thread.
All documentation about the RichTextBox says: send message (and not post).
Thus there is no message loop involved in this process and I could use these whole message sending within the GetPreferredSize function.

If that fails, I have to use a list of RichTextControls on the form. These will then pour their requested Sizes into my Forms.MessageLoop. (The test data I have has 12 rows).

modified 19-Jan-13 2:33am.

GeneralMy vote of 5 Pin
Filip D'haene13-Sep-11 12:44
memberFilip D'haene13-Sep-11 12:44 
GeneralThere is an error in using your program Pin
hambor18-Jun-11 4:34
memberhambor18-Jun-11 4:34 
GeneralThanks Pin
YZK30-Mar-11 1:25
groupYZK30-Mar-11 1:25 
GeneralMy vote of 5 Pin
DhavalShah198812328-Dec-10 21:44
memberDhavalShah198812328-Dec-10 21:44 
GeneralRight To Left Pin
alireza.noorian28-Aug-10 20:29
memberalireza.noorian28-Aug-10 20:29 
GeneralRe: Right To Left Pin
mrwisdom29-Aug-10 15:22
membermrwisdom29-Aug-10 15:22 
GeneralClickable Web Links Pin
flippydeflippydebop23-Jul-10 7:13
memberflippydeflippydebop23-Jul-10 7:13 
QuestionHow to change the text data to rtf byte data for database Pin 2:33 2:33 
QuestionHow to change Text color Pin 2:05 2:05 

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.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171207.1 | Last Updated 9 Jul 2014
Article Copyright 2008 by mrwisdom
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid