3

This is something that has been bugging me for a while as it is easily fixed but not desirable.

I have a DataGridView that has 5 columns. The first is called ID.

In vb.net the following line gives an error "Object reference not set to an instance of an object":

dgvJobs.Columns("ID").Visible = False ' ERROR
dgvJobs.Columns(0).Visible = False ' OK

Obviously using the name is much better than a hard coded value to reference the column but wondering if there is anything i can do to get this to work correctly?

The datagridview datasource is BindingSource control with the datasource being a dataset.

EDIT: Based on the answer I have created the following function that does exactly as I need:

Private Function GetColName(ByVal name As String, ByRef dgv As DataGridView) As Integer
    Dim retVal As Integer

    For Each col As DataGridViewColumn In dgv.Columns
        If col.HeaderText = name Then
            retVal = col.Index
            Exit For
        End If
    Next

    Return retVal

End Function

Useage:

dgvJobs.Columns(GetColName("ID", dgvJobs)).Visible = False
1
  • Note also, the DataGridViewColumn class has a property "HeaderText" which indicates the name to Show on the grid ! Commented Jan 7, 2010 at 16:15

3 Answers 3

2

Two tips:

1- By default, the Winforms designer creates an object in your forms Class for every column that exists in a DataGridView. So if you have a column named MyIdColumn, for instance, you should be able to access the column in the form code like this:

Me.MyIdColumn.Visible = False

If you want to access an element of the DataGridView, you could do something like this:

Dim value = dgv.Item(MyIdColumn.Index, rowIndex).Value

Using this trick, if the column name changes, there's no problem because you reference the column directly instead of a string representing a column name that could change.

2- Your GetColName method could be better; I would transform it into an extension method:

<System.Runtime.CompilerServices.Extension()> _
Private Function GetColByHeaderText(ByVal dgv As DataGridView, ByVal name As String) As DataGridViewColumn

    For Each col As DataGridViewColumn In dgv.Columns
        If col.HeaderText = name Then
            Return col
        End If
    Next

    Return Nothing

End Function

Usage:

dgv.GetColByHeaderText("ID").Visible = False

A lot nicer IMO!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this is an excellent answer and learnt something new. You are right, it is much nicer. I did make a change the function to Friend and placed it in a module. Excellent, thanks.
2

Perhaps the column is not called what you think it is?

Have you checked the Columns(0).Name property to verify?

It might have been called "tablename_ID" or something by the BindingSource

1 Comment

you are right, the column name is called "DataGridViewTextBoxColumn17". Bit odd, why would the BindingSource change this?
1

Public Class Form2 Private list As List(Of Person) Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load CreateDGV() PopulatingDGV()

End Sub

Private Sub CreateDGV()
    dataGridView1.AllowUserToAddRows = False
    dataGridView1.RowHeadersVisible = False

    dataGridView1.Columns.Add("col1", "Column 1")
    Dim column2 As DataGridViewComboBoxColumn = CreateComboBoxColumn1()
    Dim column3 As DataGridViewComboBoxColumn = CreateComboBoxColumn2()
    dataGridView1.Columns.Add(column2)
    dataGridView1.Columns.Add(column3)
    'adding an event:
    'DataGridView1.EditingControlShowing += New DataGridViewEditingControlShowingEventHandler(AddressOf dataGridView1_EditingControlShowing)
    'DataGridView1.DataError += New DataGridViewDataErrorEventHandler(AddressOf dataGridView1_DataError)
End Sub

Private Function CreateComboBoxColumn1() As DataGridViewComboBoxColumn
    Dim column As New DataGridViewComboBoxColumn()
    If True Then
        column.Name = "column2"
        column.HeaderText = "Column 2"
        column.DropDownWidth = 120
        column.Width = 120
        column.MaxDropDownItems = 3
        column.Items.AddRange(New String() {"First name", "Last name", "E-mail"})
        column.FlatStyle = FlatStyle.Flat
    End If
    Return column
End Function

Private Function CreateComboBoxColumn2() As DataGridViewComboBoxColumn
    Dim column As New DataGridViewComboBoxColumn()
    If True Then
        column.Name = "column3"
        column.HeaderText = "Column 3"
        column.DropDownWidth = 150
        column.Width = 150
        column.MaxDropDownItems = 3
        column.FlatStyle = FlatStyle.Flat
    End If
    Return column
End Function
Private Sub PopulatingDGV()
    '1.ST COLUMN: some test data to populate dgv
    Dim companies As String() = {"Indian Info", "Cybex", "Admin"}
    For i As Integer = 0 To companies.Length - 1
        dataGridView1.Rows.Add(companies(i))
    Next

    '2.ND COLUMN: creating a generic list (of your data from the file):
    'I will not populate it from the file, only invent some example data:
    Dim persons As Person() = New Person() {New Person("Monica", "Trotsky", "[email protected]"), New Person("Budh", "sagar", "[email protected]")}
    list = New List(Of Person)()
    For Each p As Person In persons
        list.Add(p)
    Next
End Sub


Private Sub DataGridView1_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles DataGridView1.EditingControlShowing
    Try
        If DataGridView1.CurrentCell.ColumnIndex = 1 Then
            Dim combo As ComboBox = TryCast(e.Control, ComboBox)
            If combo IsNot Nothing Then
                RemoveHandler combo.SelectedIndexChanged, New EventHandler(AddressOf comboBox_SelectedIndexChanged)
                AddHandler combo.SelectedIndexChanged, New EventHandler(AddressOf comboBox_SelectedIndexChanged)
            End If
        End If
    Catch ex As Exception
        MessageBox.Show("Error:" & vbLf & vbLf & ex.Message)
    End Try
End Sub
Private Sub comboBox_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
    Try
        Dim cb As ComboBox = DirectCast(sender, ComboBox)
        Dim selection As String = cb.Text
        If selection <> [String].Empty Then
            For Each dgvColumn As DataGridViewColumn In dataGridView1.Columns
                If dgvColumn.Name = "column3" Then
                    Dim row As Integer = dataGridView1.CurrentCell.RowIndex
                    Dim cell As DataGridViewComboBoxCell = DirectCast(dataGridView1(2, row), DataGridViewComboBoxCell)
                    'cell.Items.Clear();
                    Select Case selection
                        Case "First name"
                            If True Then
                                cell.DataSource = list
                                cell.DisplayMember = "firstName"
                                cell.ValueMember = cell.DisplayMember
                                Exit Select
                            End If
                        Case "Last name"
                            If True Then
                                cell.DataSource = list
                                cell.DisplayMember = "lastName"
                                cell.ValueMember = cell.DisplayMember
                                Exit Select
                            End If
                        Case "E-mail"
                            If True Then
                                cell.DataSource = list
                                cell.DisplayMember = "eMail"
                                cell.ValueMember = cell.DisplayMember
                                Exit Select
                            End If
                    End Select
                End If
            Next
        End If
    Catch ex As Exception
        MessageBox.Show("Error:" & vbLf & vbLf & ex.Message)
    End Try
End Sub

Friend Class Person
    Public Property firstName() As String
        Get
            Return m_firstName
        End Get
        Set(ByVal value As String)
            m_firstName = Value
        End Set
    End Property
    Private m_firstName As String
    Public Property lastName() As String
        Get
            Return m_lastName
        End Get
        Set(ByVal value As String)
            m_lastName = Value
        End Set
    End Property
    Private m_lastName As String
    Public Property eMail() As String
        Get
            Return m_eMail
        End Get
        Set(ByVal value As String)
            m_eMail = Value
        End Set
    End Property
    Private m_eMail As String

    Public Sub New(ByVal _fn As String, ByVal _ln As String, ByVal _em As String)
        firstName = _fn
        lastName = _ln
        eMail = _em
    End Sub
End Class

Private Sub DataGridView1_DataError(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewDataErrorEventArgs) Handles DataGridView1.DataError
    If e.Exception IsNot Nothing AndAlso e.Context = DataGridViewDataErrorContexts.Commit Then
        MessageBox.Show("CustomerID value must be unique.")
    End If
End Sub

End Class

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.