2010-01-07 4 views
3

Ceci est quelque chose qui m'a dérangé pendant un certain temps car il est facilement résolu mais pas souhaitable.DataGridView.Column (ColumnName as String) donne l'erreur "Référence d'objet non définie sur une instance d'un objet"

J'ai un DataGridView qui a 5 colonnes. Le premier est appelé ID.

En vb.net la ligne suivante donne une erreur « référence d'objet non définie à une instance d'un objet »:

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

De toute évidence en utilisant le nom est bien mieux qu'une valeur codée en dur pour faire référence à la colonne mais je me demande s'il y a quelque chose que je peux faire pour que cela fonctionne correctement?

La source de données datagridview est un contrôle BindingSource dont la source de données est un ensemble de données.

EDIT: Sur la base de la réponse que j'ai créé la fonction suivante qui fait exactement comme je l'ai besoin:

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 
+0

Notez également, la classe DataGridViewColumn possède une propriété "HeaderText" qui indique le nom à afficher sur la grille! –

Répondre

2

Deux conseils:

1- Par défaut, le concepteur Winforms crée un objet dans vos formulaires de classe pour chaque colonne qui existe dans un DataGridView. Donc, si vous avez une colonne nommée MyIdColumn, par exemple, vous devriez pouvoir accéder à la colonne dans le code de formulaire comme ceci:

Me.MyIdColumn.Visible = False 

Si vous souhaitez accéder à un élément du DataGridView, vous pouvez faire quelque chose comme ceci:

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

en utilisant cette astuce, si les changements de nom de colonne, il n'y a pas de problème parce que vous faites référence à la colonne directement au lieu d'une chaîne représentant un nom de colonne qui pourrait changer.

2- Votre méthode GetColName pourrait être meilleure; Je le transformer en une méthode d'extension:

<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 

Utilisation:

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

beaucoup plus agréable OMI!

+0

Merci, c'est une excellente réponse et j'ai appris quelque chose de nouveau. Vous avez raison, c'est beaucoup plus agréable. J'ai fait changer la fonction à Friend et l'ai placée dans un module. Excellent, merci. – Belliez

2

Peut-être que la colonne n'est pas appelé ce que vous pensez c'est?

Avez-vous vérifié la propriété Columns (0) .Name à vérifier?

Il aurait été appelé « tablename_ID » ou quelque chose par les BindingSource

+0

vous avez raison, le nom de la colonne s'appelle "DataGridViewTextBoxColumn17". Bit impair, pourquoi le BindingSource changerait-il ceci? – Belliez

+0

Je vais ajouter le code à cette réponse – Belliez

1

Classe publique Form2 Liste privée liste (de la personne) Sous Form2_Load privé (expéditeur de ByVal comme System.Object, ByVal e comme System.EventArgs) Poignées MyBase.Charge 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

Questions connexes