Here's one option....
Create a dictionary object to store the names...
Private headerNames As Dictionary(Of Int32, String) = Nothing
... and set the names when the RowType is Header. Then when you get to the DataRow you can use the cells index to pull the header name that was stored when the header row was databound.
Protected Sub GridView1_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
If e.Row.RowType = DataControlRowType.Header Then
headerNames = New Dictionary(Of Int32, String)
For i As Int32 = 0 To e.Row.Cells.Count - 1
headerNames.Add(i, e.Row.Cells(i).Text)
Next
End If
If e.Row.RowType = DataControlRowType.DataRow Then
For i As Int32 = 0 To e.Row.Cells.Count - 1
Dim cell As TableCell = e.Row.Cells(i)
Dim headText As String = headerNames(i).ToString()
Next
End If
End Sub