20

I have a datagridview with the following data.

ContactType        |        Contact
------------------------------------
Phone              |       894356458
Email              |     xyz@abc.com

Here, I need to display the data "xyz@abc.com" as a hyperlink, with a tooltip "Click to send email". The number data "894356458" should not have a hyperlink.

Any ideas???

TIA!

Sandeep
  • 5,581
  • 10
  • 42
  • 62
  • I've edited my answer, explaining how to use my first option in your case better (by hiding one column and using DataPropertyName) as well as offering a second variation on the answer where you keep the text column. – David Hall Jun 05 '12 at 13:00

2 Answers2

26

The DataGridView has a column type for this, the DataGridViewLinkColumn.

You need to databind this column type manually, where DataPropertyName sets the column to bind to in the grid's datasource:

DataGridViewLinkColumn col = new DataGridViewLinkColumn();
col.DataPropertyName = "Contact";
col.Name = "Contact";       
dataGridView1.Columns.Add(col);

You will also want to hide the autogenerated text column that comes from the Contact property of the grid.

Also, as with the DataGridViewButtonColumn you need to handle the user interaction yourself by responding to the CellContentClick event.


To then change cell values that are not hyperlinks to plain text you need to replace the link cell type with the textbox cell. In the example below I've done this during the DataBindingComplete event:

void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
    foreach (DataGridViewRow r in dataGridView1.Rows)
    {
        if (!System.Uri.IsWellFormedUriString(r.Cells["Contact"].Value.ToString(), UriKind.Absolute))
        {
            r.Cells["Contact"] = new DataGridViewTextBoxCell();
        }
    }
}

You can also do this from the other direction, changing the DataGridViewTextBoxCell to a DataGridViewLinkCell I suggest this second since you will need to apply any changes that apply to all links to every cell.

This does have the advantage though that you will not then need to hide the autogenerated column, so may suit you best.

void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
    foreach (DataGridViewRow r in dataGridView1.Rows)
    {
        if (System.Uri.IsWellFormedUriString(r.Cells["Contact"].Value.ToString(), UriKind.Absolute))
        {
            r.Cells["Contact"] = new DataGridViewLinkCell();
            // Note that if I want a different link colour for example it must go here
            DataGridViewLinkCell c = r.Cells["Contact"] as DataGridViewLinkCell;
            c.LinkColor = Color.Green;
        }
    }
}
David Hall
  • 32,624
  • 10
  • 90
  • 127
  • As an aside - one nice thing with the datagridview is that when responding to the cell content click you can do something like open a Voip service when a phone number is clicked. – David Hall Jun 05 '12 at 11:58
  • Alternatively, couldn't you do the reverse? Define your grid by default (TextBoxCell) as you would normally, then hyperlink the cell(s) that you want in each row? Just wondering why you defaulted to LinkCells then explicitly changed back to TextBox – B L Jun 05 '12 at 12:21
  • 1
    @Brett the hyperlink column has some additional properties and behaviours that are handy, such as visited link colour and TrackVisitedState - sure you could do it the other way around but I think this way is more convenient. – David Hall Jun 05 '12 at 12:24
  • 1
    Well, this solution sounds good. But the datasource for this gridview is a List where myClass has properties - ContactType, Contact. So it's just setting the datasource to the gridview. I'll not be adding rows and columns manually here. In this case, how do we tackle the issue? – Sandeep Jun 05 '12 at 12:28
  • David might have better insight on this, but if your database/datasource structure is static, you can still manually define the columns in your DataGrid and do the binding without overwriting the behavior you defined, I believe. – B L Jun 05 '12 at 12:41
  • @Brett - I'm not sure what you mean by "manually define the columns" here - do you mean in the designer? Or do you mean using the autogenerated textbox column and changing some cells to be hyperlinks? both would work of course, and in this case it might suit the Sandeep better. Maybe post your own answer. Or I'll edit it into mine. – David Hall Jun 05 '12 at 12:48
  • @David - Yes, I was referring to using the designer. He mentioned that he drives his grid structure by setting and forgetting the datasource property of the grid to his dataset, so as long as the structure of that set isn't dynamic he would be ok I believe. I didn't make my own answer because yours addresses the question just fine, where as this is referring to databinding :) – B L Jun 05 '12 at 12:57
  • @Brett I just put in what I believe you are suggesting. Does this match your thought? For me it is all much of a muchness and I gave the answer I did first since I was thinking of it as a link column that has plain text, rather then as a text column that has links. So certainly thanks for the questions making me think more! :) – David Hall Jun 05 '12 at 12:57
  • @David - I wasn't disagreeing with your approach at all, I was mainly just curious because I wouldn't have thought to do it that way, and I was wondering what you gained from doing so. Sorry for the mis-communication, but I was referring to using the designer to drive structure as it wouldn't break the binding, since presumably he's doing something like: "dataGridView.DataSource = List" when retrieving the information. – B L Jun 05 '12 at 13:03
  • @Brett no problem, I didn't take it as disagreement at all, and always nice to hear questions and reflect on my habits. I avoid the designer for the DGV 99% of the time, and always use DataSources of BindingList - I've not ever found that doing this stuff in code breaks binding, in fact just the opposite, when I have tried the designer things often go pear shaped for me. – David Hall Jun 05 '12 at 13:07
1

You can change style of whole column in DataGridView. This is also a way to make column link column.

DataGridViewCellStyle cellStyle = new DataGridViewCellStyle();
        cellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
        cellStyle.ForeColor = Color.LightBlue;
        cellStyle.SelectionForeColor = Color.Black;
        cellStyle.Font = new Font(FontFamily.GenericSansSerif, 10, FontStyle.Underline);
        dataGridView.Columns[1].DefaultCellStyle = cellStyle;
Saleem Kalro
  • 1,046
  • 9
  • 12