Search code examples
vb.netvisual-studio-2010datagridviewdatagridviewlinkcolumn

Creating a DataGridView Programatically and add clickable cells


Evening

I am struggling to achieve what I have set out todo! In a nutshell I am working with the Google Drive API to create an app in VB.net that allows you to view / download files etc.

Basically I am planning on using a couple of different api's for the different cloud provider s I have. The stage I have got to is that I have my collection of files and there various properties in a list. On load I am checking to see if a google account has been added to my program and if so creating a new tabpage on a tabcontrol, I then create the datagridview and add it to the collection on the new tab page. This works fine and displays all my data as is.

What I am trying to achieve is adding a clickable link to my download column instead of displaying the url. I have been trying to manipulate the code found here C# DataGridViewLinkCell Display after converting it to vb.net. This is basically what I have ended up with:

If My.Settings.GoogleClientID <> "" Then
            Dim GD As New Properties.GDrive
            GD.APIClientID = My.Settings.GoogleClientID
            GD.APIClientSecret = My.Settings.GoogleClientSecret

            clsDrive.GD = GD
            clsDrive.GetSpace()
            clsDrive.RefreshFiles()
            Dim GoogleDriveTab As New TabPage
            GoogleDriveTab.Text = "Google Drive"
            tc_CloudManager.TabPages.Add(GoogleDriveTab)

            Dim GoogleDriveDGV As New DataGridView
            GoogleDriveDGV.Name = "GoogleDriveDGV"
            GoogleDriveDGV.Dock = DockStyle.Fill
            GoogleDriveDGV.Columns.Add("FileTitle", "File Title")
            GoogleDriveDGV.Columns.Add("FileExtension", "File Extension")
            GoogleDriveDGV.Columns.Add("FileSize", "File Size")
            Dim dgvlc As New DataGridViewLinkColumn()
            dgvlc.ActiveLinkColor = Color.Blue
            dgvlc.HeaderText = "Download"
            GoogleDriveDGV.Columns.Add(dgvlc)
            GoogleDriveDGV.RowHeadersVisible = False
            Dim c As New customcolumn()
            GoogleDriveDGV.Columns.Add(c)

            For i As Integer = 0 To GoogleDriveDGV.Columns.Count - 1
                GoogleDriveDGV.Columns(i).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
            Next
            Try
                For Each DriveFile In GD.DriveFiles
                    Dim row As DataGridViewRow = DirectCast(GoogleDriveDGV.Rows(0).Clone, DataGridViewRow)
                    Dim title As String = DriveFile.Title
                    If title.Length > 60 Then
                        title = title.Substring(0, 60)
                    End If

                    Dim fs As Integer = DriveFile.FileSize
                    Dim fsf As String
                    If fs > 1048576 Then
                        fsf = Math.Round(fs / 1048576, 2) & " MB"
                    Else
                        fsf = fs & " Bytes"
                    End If
                    Dim fe As String
                    If DriveFile.FileExtension = "" Then
                        fe = "Folder"
                    Else
                        fe = DriveFile.FileExtension
                    End If

                    row.Cells(0).Value = title
                    row.Cells(1).Value = fe
                    row.Cells(2).Value = fsf
                    row.Cells(3).Value = "Download File"
                    DirectCast(GoogleDriveDGV.Columns(3), customcolumn).urls.Add(3, DriveFile.DownloadUrl)
                Next
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try

            GoogleDriveTab.Controls.Add(GoogleDriveDGV)
        End If
    End Sub
    Class customcolumn
        Inherits System.Windows.Forms.DataGridViewLinkColumn
        Public urls As New Dictionary(Of Integer, String)()
    End Class

    Private Sub GoogleDriveDGV_CellContentClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs)
        For Each url As KeyValuePair(Of Integer, String) In DirectCast(GoogleDriveDGV.Columns(e.ColumnIndex), customcolumn).urls
            If url.Key = e.RowIndex Then
                Process.Start(url.Value)
                Exit For
            End If
        Next
    End Sub

I have two problems that I cant figure out:

1) GoogleDriveDGV is not declared here : For Each url As KeyValuePair(Of Integer, String) In DirectCast(GoogleDriveDGV.Columns(e.ColumnIndex), customcolumn).urls

2) If I comment out the GoogleDriveDGV_CellContentClick sub and just try to populate the datagridview I get System.InvalidCastException: Unable to cast object of type 'System.Windows.Forms.DataGridViewLinkColumn' to type 'customcolumn' here DirectCast(GoogleDriveDGV.Columns(3), customcolumn).urls.Add(3, DriveFile.DownloadUrl)

Can anyone let me know if what I am trying to achieve is possible and any hints?

Update!!!

I now have this:

If My.Settings.GoogleClientID <> "" Then
            Dim GD As New Properties.GDrive
            GD.APIClientID = My.Settings.GoogleClientID
            GD.APIClientSecret = My.Settings.GoogleClientSecret

            clsDrive.GD = GD
            clsDrive.GetSpace()
            clsDrive.RefreshFiles()


            Dim GoogleDriveTab As New TabPage
            GoogleDriveTab.Text = "Google Drive"
            tc_CloudManager.TabPages.Add(GoogleDriveTab)

            Dim GoogleDriveDGV As New DataGridView
            GoogleDriveDGV.Name = "GoogleDriveDGV"
            GoogleDriveDGV.Dock = DockStyle.Fill
            GoogleDriveDGV.Columns.Add("FileTitle", "File Title")
            GoogleDriveDGV.Columns.Add("FileExtension", "File Extension")
            GoogleDriveDGV.Columns.Add("FileSize", "File Size")
            Dim c As New customcolumn()
            GoogleDriveDGV.Columns.Add(c)
            GoogleDriveDGV.RowHeadersVisible = False

            For i As Integer = 0 To GoogleDriveDGV.Columns.Count - 1
                GoogleDriveDGV.Columns(i).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
            Next
            Dim trow As Integer = 0
            Try
                For Each DriveFile In GD.DriveFiles
                    Dim row As DataGridViewRow = DirectCast(GoogleDriveDGV.Rows(0).Clone, DataGridViewRow)
                    Dim title As String = DriveFile.Title
                    If title.Length > 60 Then
                        title = title.Substring(0, 60)
                    End If

                    Dim fs As Integer = DriveFile.FileSize
                    Dim fsf As String
                    If fs > 1048576 Then
                        fsf = Math.Round(fs / 1048576, 2) & " MB"
                    Else
                        fsf = fs & " Bytes"
                    End If
                    Dim fe As String
                    If DriveFile.FileExtension = "" Then
                        fe = "Folder"
                    Else
                        fe = DriveFile.FileExtension
                    End If

                    row.Cells(0).Value = title
                    row.Cells(1).Value = fe
                    row.Cells(2).Value = fsf
                    row.Cells(3).Value = "Download"

                    DirectCast(GoogleDriveDGV.Columns(3), customcolumn).urls.Add(trow, DriveFile.DownloadUrl)
                    GoogleDriveDGV.Rows.Add(row)
                    trow = trow + 1

                Next
            Catch ex As Exception
                MsgBox(ex.ToString)
            End Try
            GoogleDriveTab.Controls.Add(GoogleDriveDGV)
        End If
    End Sub


    Class customcolumn
        Inherits System.Windows.Forms.DataGridViewLinkColumn
        Public urls As New Dictionary(Of Integer, String)()
    End Class


    'Private Sub GoogleDriveDGV_CellContentClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs)
    '    For Each url As KeyValuePair(Of Integer, String) In DirectCast(GoogleDriveDGV.Columns(e.ColumnIndex), customcolumn).urls
    '        If url.Key = e.RowIndex Then
    '            Process.Start(url.Value)
    '            Exit For
    '        End If
    '    Next
    'End Sub

Which is almost there, I now have the datagridview filled with the items and a download link, just cant work out how to solve issue 1 above :-(


Solution

  • Would you believe it I worked it out :-)

    Basically I needed to add a handler.

    Full code:

     Private Sub CloudManager_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            If My.Settings.GoogleClientID <> "" Then
                Dim GD As New Properties.GDrive
                GD.APIClientID = My.Settings.GoogleClientID
                GD.APIClientSecret = My.Settings.GoogleClientSecret
    
                clsDrive.GD = GD
                clsDrive.GetSpace()
                clsDrive.RefreshFiles()
    
    
                Dim GoogleDriveTab As New TabPage
                GoogleDriveTab.Text = "Google Drive"
                tc_CloudManager.TabPages.Add(GoogleDriveTab)
    
                Dim GoogleDriveDGV As New DataGridView
    
                GoogleDriveDGV.Name = "GoogleDriveDGV"
                GoogleDriveDGV.Dock = DockStyle.Fill
                GoogleDriveDGV.Columns.Add("FileTitle", "File Title")
                GoogleDriveDGV.Columns.Add("FileExtension", "File Extension")
                GoogleDriveDGV.Columns.Add("FileSize", "File Size")
                Dim c As New customcolumn()
                GoogleDriveDGV.Columns.Add(c)
                AddHandler GoogleDriveDGV.CellContentClick, AddressOf GoogleDriveDGV_CellContentClick
                GoogleDriveDGV.RowHeadersVisible = False
    
                For i As Integer = 0 To GoogleDriveDGV.Columns.Count - 1
                    GoogleDriveDGV.Columns(i).AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
                Next
                Dim trow As Integer = 0
                Try
                    For Each DriveFile In GD.DriveFiles
                        Dim row As DataGridViewRow = DirectCast(GoogleDriveDGV.Rows(0).Clone, DataGridViewRow)
                        Dim title As String = DriveFile.Title
                        If title.Length > 60 Then
                            title = title.Substring(0, 60)
                        End If
    
                        Dim fs As Integer = DriveFile.FileSize
                        Dim fsf As String
                        If fs > 1048576 Then
                            fsf = Math.Round(fs / 1048576, 2) & " MB"
                        Else
                            fsf = fs & " Bytes"
                        End If
                        Dim fe As String
                        If DriveFile.FileExtension = "" Then
                            fe = "Folder"
                        Else
                            fe = DriveFile.FileExtension
                        End If
    
                        row.Cells(0).Value = title
                        row.Cells(1).Value = fe
                        row.Cells(2).Value = fsf
                        row.Cells(3).Value = "Download"
    
                        DirectCast(GoogleDriveDGV.Columns(3), customcolumn).urls.Add(trow, DriveFile.DownloadUrl)
                        GoogleDriveDGV.Rows.Add(row)
                        trow = trow + 1
    
                    Next
                Catch ex As Exception
                    MsgBox(ex.ToString)
                End Try
                GoogleDriveTab.Controls.Add(GoogleDriveDGV)
            End If
        End Sub
    
    
        Class customcolumn
            Inherits System.Windows.Forms.DataGridViewLinkColumn
            Public urls As New Dictionary(Of Integer, String)()
        End Class
    
    
        Private Sub GoogleDriveDGV_CellContentClick(ByVal sender As Object, ByVal e As DataGridViewCellEventArgs)
            For Each url As KeyValuePair(Of Integer, String) In DirectCast(sender.Columns(e.ColumnIndex), customcolumn).urls
                If url.Key = e.RowIndex Then
                    Process.Start(url.Value)
                    Exit For
                End If
            Next
        End Sub
    
    
    End Class