DataGridView.Column(ColumnName as String) gives error "Object reference not set to an instance of an object"

14,499

Solution 1

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!

Solution 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

Solution 3

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

Share:
14,499
Belliez
Author by

Belliez

I'm a software developer and own a small PC / Laptop repair company called PCease.com. I love to program full time, part-time, in my own time or when I can....

Updated on June 04, 2022

Comments

  • Belliez
    Belliez almost 2 years

    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