Search code examples
c#datagridview

Unable to open a link with UseColumnTexForLink: True


I retrieve external data including links to profile pages

In the "Url" column of the DataGridView, I configured it like this:

Column Type: DataGridViewLinkColumn

UseColumnTexForLink: True

Text: See profile

When I run the program, I receive the data with the links and the text "See profile", but when I click on it, an exception is thrown: "System.ComponentModel.Win32Exception: 'The specified file cannot be found'".

On the other hand, with UseColumnTexForLink= False and Text=empty, the links open correctly.

Do you have any suggestions or ideas?

Thanks

foreach (UserRank user in userRanks)
 {
    // Adding data to the DataGridView
    dataGridViewTopRanking.Rows.Add(user.NickName, user.Rank, user.FollowerCount, user.PositionShared, user.LeaderboardUrl);
 }


private void dataGridViewTopRanking_CellContentClick(object sender, DataGridViewCellEventArgs e)
 {
     string url = dataGridViewTopRanking.Rows[e.RowIndex].Cells["Link"].Value.ToString();
     System.Diagnostics.Process.Start(url);
 }

Solution

  • In DataGridViewLinkColumn, using the UseColumnTextForLinkValue property to display the value of the Text property instead of the link is useful in data-bound scenarios where you can get the actual value (the link) from the data source through the DataBoundItem property of the current row.

    That does not work when you populate the grid manually because setting the property of the owning column to true also sets the DataGridViewLinkCell.UseColumnTextForLinkValue of every cell to true. Which means, the DataGridViewLinkCell.Value property will always return the value of the Text property of the owning column. In this case, no way to get the actual value unless you store it somewhere, in the Tag property for example. So, you're getting the exception because you're passing See profile to the Process.Start(...) method as the fileName param.

    As an alternative to storing actual values, implement the DataGridView.CellFormatting

    private void dataGridViewTopRanking_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
    {
        int linkCol = 1; // the index of your link column...
                
        if (e.RowIndex >= 0 && e.ColumnIndex == linkCol && e.Value != null)
        {
            e.Value = "See profile";
            e.FormattingApplied = true;
        }
    }
    

    ... and the CellContentClick event:

    private void dataGridViewTopRanking_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        int linkCol = 1;
        var dgv = sender as DataGridView;
    
        if (e.RowIndex >= 0 && e.ColumnIndex == linkCol)
        {
            var url = dgv[linkCol, e.RowIndex].Value?.ToString();
    
            if (!string.IsNullOrEmpty(url))
            {
                Process.Start(new ProcessStartInfo
                {
                    FileName = url,
                    UseShellExecute = true
                });
            }
        }
    }
    

    Make sure url is a valid path/UNC/Uri and don't forget to reset the UseColumnTextForLinkValue property to its default value. You may also want to have the Process.Start call within a try...catch block in case something goes wrong.