Richtextbox within a datagrid view

Hi there,

I'm quite new to this so please bear with me.

I'm using Visual studio and vb.net.

I'm trying to workout how to format text within a datagridview. I've read lots of articles and have tried in vain to adapt other source code to do what I want.

Basically I want to format different lines within a richtextbox cell with different styles.

In my code I populate one column with test data, this will eventually be pulled from a database.
RoundTitle = "Round 1:"
RoundTitleData = "abc123"
CustomerTitle = "Customer:"
CustomerData = "ABC Ltd"

When the datagridcell is created I would like to say
RoundTitle = Bold - Black
RoundTtileDate  = Normal - Black

I can't work out how to pass the data to the RichTextBox control within the datagridview and from there how to format it.

My pathetic attempt to complete this task is detailed below.  I have also attached the project.

I would be grateful of any help and guidance

Regards
Paul
Public Class Form1
    

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        Dim MyCalendarTable As New DataTable("DiaryDates")

        MyCalendarTable.Columns.Add("Col1")
        Pop_Col1(MyCalendarTable)

        Dim Col1 As New DataGridViewCalendarColumn
        Col1.DataPropertyName = "Col1"
        Col1.HeaderText = "Col1"
        Col1.Width = 150
        Col1.ReadOnly = True
        Me.DataGridView1.Columns.Add(Col1)

        DataGridView1.DataSource = MyCalendarTable

        For Each row As DataGridViewRow In DataGridView1.Rows
            row.Height = 160
        Next

    End Sub

    Private Sub Pop_Col1(ByVal table As DataTable)

        Dim MyRow As DataRow
        Dim i As Integer = 0

        Dim RoundTitle As String
        Dim RoundTitleData As String

        Dim CustomerTitle As String
        Dim CustomerData As String

        Do Until i = 2

            RoundTitle = "Round 1:"
            RoundTitleData = "abc123"

            CustomerTitle = "Customer:"
            CustomerData = "ABC Ltd"

            MyRow = table.NewRow()
            MyRow("Col1") = RoundTitle & RoundTitleData & vbCr & CustomerTitle & CustomerData
            table.Rows.Add(MyRow)
            MyRow = Nothing
            i += 1
        Loop

    End Sub

End Class

Public Class DataGridViewCalendarColumn
    Inherits DataGridViewColumn

    Public Sub New()
        Me.CellTemplate = _
         New DataGridViewCalendarCell()
        Me.ReadOnly = True
    End Sub
End Class

Public Class DataGridViewCalendarCell
    Inherits DataGridViewTextBoxCell
    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
          ByVal initialFormattedValue As Object, _
          ByVal dataGridViewCellStyle As DataGridViewCellStyle)

        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
        Dim ctl As RichTextBox = CType(DataGridView.EditingControl, RichTextBox)
        ctl.Rtf = CType(Me.Value, String)
    End Sub
    Public Overrides ReadOnly Property EditType() As Type
        Get
            Return GetType(RichTextBox)
        End Get
    End Property
    Public Overrides ReadOnly Property ValueType() As Type
        Get
            Return GetType(String)
        End Get
    End Property
    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get
            Return String.Empty
        End Get
    End Property
End Class

Open in new window

DataGridViewCalendarCell.zip
LVL 1
PaulEllAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SawinerCommented:
Actually, you were very close.
As far as I can tell, you got 2 options:

1. you can learn the RTF format. It's not a very nice format, but you can create text anyway you want, and since the value you insert into row is the actual RTF property, it will be parsed correctly.
Not much more to say about this choice.

2. using your own simple code code, or value.
Currently, you are passing string. If you would like to stick to it you can use "codes" to pass styles you want. e.g.

"<start color=Color.Red>Red Text</start><start color=Color.Black>with</start><start color=Color.Red>Green Text",
and parse that in your InitializeEditingControl method.

a better approach would be to use a custom class rather than string, one that holds font/backcolor/all other styles you would like to apply, and then pass that custom class instead of the string.
If you want multiple custom styles in one text (which you probably will), you can create a custom collection class having a collection of the custom class, and passing that.

Also note you can have better control over the appear of the rich text box in the row if you create a new control inheriting from RichTextBox and InitializeEditingControl.

Good luck.
0
PaulEllAuthor Commented:
Hi CodeCruiser,

Thanks for the reply.

Yes I have seen both examples and have spent many days on

http://www.codeproject.com/KB/grid/RtfInDataGridView.aspx

Converting it to VB and then trying to adapt the code to what I want without any joy.

Bascially all I am trying to do is populate a rich text box within a datagrid with a string that we be derived from a database.  The rich text box needs to be read only but I will need to format various lines of the string, so certain sections are bold and depending on conditions a variety of colours.

The examples I have found on the net and the two you highlight rely on keystrokes to amend the display.  Where my knowledge level falls down is how to initiate the rich text box and how to apply the formatting at run time based on various conditions.

Regards
Paul
0
Rowby Goren Makes an Impact on Screen and Online

Learn about longtime user Rowby Goren and his great contributions to the site. We explore his method for posing questions that are likely to yield a solution, and take a look at how his career transformed from a Hollywood writer to a website entrepreneur.

PaulEllAuthor Commented:
Hi Sawiner,

Thank you very much for your reply.  

This would be great !
"<start color=Color.Red>Red Text</start><start color=Color.Black>with</start><start color=Color.Red>Green Text",
and parse that in your InitializeEditingControl method

This would be fantastic !
a better approach would be to use a custom class rather than string, one that holds font/backcolor/all other styles you would like to apply, and then pass that custom class instead of the string.
If you want multiple custom styles in one text (which you probably will), you can create a custom collection class having a collection of the custom class, and passing that.

Also note you can have better control over the appear of the rich text box in the row if you create a new control inheriting from RichTextBox and InitializeEditingControl.

But this is where my knowledge level is letting me down, I simply cannot fathom how to achieve this. I have made a custom column that has a date picker, as per the MS examples and have converted several C# examples to VB that use keystrokes to render the rich text box.

I'm just a newbie at the moment trying to write a simple booking program for the village hall.  The old lady who runs it has asked for the display to be different colours to help here work out what is happening,  I thought it would be easy ! How wrong can you be ?

Regards
Paul
0
CodeCruiserCommented:
You apply formatting to the rtb by using this syntax

rtb.selectionstart = 5
rtb.selectionlength = 10
rtb.selectionfont = ...
rtb.Selectioncolor = ...


http://www.startvbdotnet.com/controls/rtb.aspx



0
SawinerCommented:
PaulEll well currently, you are using a string.
you just need to change that to a custom class you create, such as this:

public Class RtbTextData
     public Text As String
     public Color As Color
     public Font As Font;
     //etc ..
     //you can also have some nice constructors in here
End Class

then, in your DataGridViewCalendarCell class:

Public Overrides ReadOnly Property ValueType() As Type
    Get
        Return GetType(RtbTextData());
    End Get
End Property

Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
      ByVal initialFormattedValue As Object, _
      ByVal dataGridViewCellStyle As DataGridViewCellStyle)

    MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
    Dim ctl As RichTextBox = CType(DataGridView.EditingControl, RichTextBox)

    Dim value as RtbTextData() = CType(Me.Value, RtbTextData());
    For Each rtd as RtbTextData In value
        AddRtd(ctl,rtd);
    Next
End Sub

private Sub AddRtd(ByValue rtb as RichTextBox, ByVal rtd as RtbTextData)
    rtb.SelectionColor = rtd.Color;
    rtb.SelectionFont = rtd.Font;
    rtb.AppendText(rtd.Text);
End Sub

final step you need to do is pass an array of RtbTextData() to the value of the rows, instead of string:

old code:
MyRow("Col1") = RoundTitle & RoundTitleData & vbCr & CustomerTitle & CustomerData

new code:
Dim value as RtbTextData = new RtbTextData()
value.Color = Color.Red
value.Text = "My Text"
value.Font = this.Font; //default font
MyRow("Col1") = value;

Good luck
0
PaulEllAuthor Commented:
Hi there Sawiner

Thanks for the help.

I will have a bash and see if I can get it to work.

Thanks
Paul
0
PaulEllAuthor Commented:
Hi there Sawiner,

I've had a bash at putting the code together as you suggested.

Seems there is a bug in there somewhere.

I'm not sure where it is, the text ouput is the name of the project followed by RtbTextData.

I've uploaded the new code and an image of the error.

Sorry to be a pain, but could you have a look at it for me if you get a chance.
It must be something very simple.

Thanks
Paul
Public Class RtbTextData
    Public Text As String
    Public Color As Color
    Public Font As Font
    '//etc ..
    '//you can also have some nice constructors in here
End Class

Public Class DataGridViewCalendarCell
    Inherits DataGridViewTextBoxCell

    Public Overrides Sub InitializeEditingControl(ByVal rowIndex As Integer, _
      ByVal initialFormattedValue As Object, _
      ByVal dataGridViewCellStyle As DataGridViewCellStyle)

        MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle)
        Dim ctl As RichTextBox = CType(DataGridView.EditingControl, RichTextBox)

        Dim value As RtbTextData() = CType(Me.Value, RtbTextData())
        For Each rtd As RtbTextData In value
            AddRtd(ctl, rtd)
        Next
    End Sub

    Private Sub AddRtd(ByVal rtb As RichTextBox, ByVal rtd As RtbTextData)
        rtb.SelectionColor = rtd.Color
        rtb.SelectionFont = rtd.Font
        rtb.AppendText(rtd.Text)
    End Sub

    Public Overrides ReadOnly Property EditType() As Type
        Get
            Return GetType(RichTextBox)
        End Get
    End Property
    Public Overrides ReadOnly Property DefaultNewRowValue() As Object
        Get
            Return String.Empty
        End Get
    End Property

    Public Overrides ReadOnly Property ValueType() As Type
        Get
            Return GetType(RtbTextData())
        End Get
    End Property
End Class

Public Class DataGridViewCalendarColumn
    Inherits DataGridViewColumn

    Public Sub New()
        Me.CellTemplate = _
         New DataGridViewCalendarCell()
        Me.ReadOnly = True
    End Sub
End Class

Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load


        Dim MyCalendarTable As New DataTable("DiaryDates")

        MyCalendarTable.Columns.Add("Col1")
        Pop_Col1(MyCalendarTable)

        Dim Col1 As New DataGridViewCalendarColumn
        Col1.DataPropertyName = "Col1"
        Col1.HeaderText = "Col1"
        Col1.Width = 150
        Col1.ReadOnly = True
        Me.DataGridView1.Columns.Add(Col1)

        DataGridView1.DataSource = MyCalendarTable

        For Each row As DataGridViewRow In DataGridView1.Rows
            row.Height = 160
        Next

    End Sub

    Private Sub Pop_Col1(ByVal table As DataTable)

        Dim MyRow As DataRow
        Dim i As Integer = 0

        Do Until i = 2

            MyRow = table.NewRow()
            Dim value As RtbTextData = New RtbTextData()
            value.Color = Color.Red
            value.Text = "My Text"
            value.Font = Me.Font

            MyRow("Col1") = value
            table.Rows.Add(MyRow)
            MyRow = Nothing
            i += 1
        Loop

    End Sub

End Class

Open in new window

Error.gif
0
SawinerCommented:
I have to admit I was somehow wrong.
When I wrote the code and the solution it worked on my other pc which is by now deleted, but I'm not really sure how since looking at it, it seems like it shouldn't.

The problem with the DataGridView is it only offers to host a control inside a cell only when editing it, and not when viewing it, like what you want.

The "easiest" way to do what you want is probably follow this article: http://www.codeproject.com/KB/grid/RtfInDataGridView.aspx which was linked by someone at the first replies in this thread. Note that some things in there are not too nice things, although not too hard to understand. If you want to understand it you could, however you don't have to it. It just uses API that is usually wrapped by the .net FW.

Either way I apologize, and if there's anything else I can help with please say so.
0
PaulEllAuthor Commented:
Hi Sawiner,

Thanks for your help.

I have looked at http://www.codeproject.com/KB/grid/RtfInDataGridView.aspx but could not work out how to render the text properly.  It does work but only via keystrokes.

I have looked at http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_25024077.html
And
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_25343441.html

You can change the text but you have to read through the string prior to it being rendered.

What I was trying to do was say this partA of the string make it bold and black - This is partB of the string make it normal and green - This is partC make it yellow and the font family is xx.

The real goal at the end would be to say if Condition A is met then make the background of the rtf be x or make it be y

I just couldn't adapt it, so I tried to write my own.

Hope the above makes sense, I'll keep trying and will update the question if I find the solution.

It seems there are a lot of people all searching for the same solution.

0
SawinerCommented:
So for the past hour I've been reading the .net Framework code to try and understand _where_ to apply the data, because the data type in source cannot be custom, but only those who matches data base, hence string, so we need to convert it.

I found the place, but it didn't help. So instead i'm setting the actual Rtf data in the ToString() method of the custom class we created ( RtbTextData ).

Then I reached another problem:
If I try to edit cell (0,1) (row 0, col 1), it works fine.
If I try to edit cell (0,0), the color is gone.
If I try to edit cell (0,1) after editing cell (0,0), color is also gone.

then, I created another row,where things gets a bit more weird.
If I try to edit cell (1,1) after editing cells (1,0) and (0,1), in that order, color is not gone.

to conclude:
If you try to edit only cells at second columns, it works fine.
any cell you edit after editing a cell at column 0 will have it color gone as well.

I have to say i'm a bit clueless why this happens or why to solve this.
I hope you or someone else can solve this.
I do have to say it's the closest I've got.
0
SawinerCommented:
My bad, forget to upload the code (weirdly enough there isn't any edit button in the site).

Anyway I have to apologize but the code is in C#. I'm more familiar with C# and it took some time with it anyway, hope you can work with it.


Note the file is the project from CodeSouce + editing from my side


I tried to attach the file, but this site seem to have a very stupid uploading constraints.
only .zip and not .rar, using password is detected as virus, and .sou and some other files (solution files of C#) are not allowed.

I've just uploaded it:

http://www.sendspace.com/file/88x5in
0
PaulEllAuthor Commented:
Thanks for your help.

I'll download and have a look over the weekend.

The good news is that I do not need to edit a cell - They will all need to be read only anyway.

Thanks again

Paul
0
SawinerCommented:
In that case the the code i've uploaded should fit best for you.

keep me posted
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
PaulEllAuthor Commented:
HI there,

Still working on it.

Have noticed that the code project link, they are using a derived image column cell and then painting.

Am trying to replicate.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.