在将DataGridView.DataSource设置为具有列的DataTable之后,为什么无法获取任何DataGridViewColumn?

时间:2016-05-25 23:27:38

标签: vb.net winforms datagridview datatable

我需要的东西:当这个给定的Form第一次显示时,它应该创建一个数据表并将其绑定到DataGridView,我希望隐藏两个第一列。 / p>

当用户选择其他控件中的项目时,将由另一个函数将行添加到此表中。然后,用户可以使用DataGridView设置一些数据,这应该反映在绑定的DataTable

我选择使用绑定数据表,因为其中一列存储的数据类型是从我的项目中的自定义类中提供的,我希望其他列也保持强类型。

问题:当它隐藏列时,我得到“System.NullReferenceException”然后我可以验证DataGridView没有包含任何列,即使它是DataSource property设置为DataTable,其中包含列,AutoGenerateColumns属性设置为true。

出了什么问题?下面的代码(.NET 4.5,Winforms)

Private dtItens as DataTable
Private Sub DataGridViewProcessos_ParentChanged(sender As Object, e As EventArgs) _
            Handles DataGridViewProcessos.ParentChanged
    If TableViewProcessos.DataSource Is Nothing Then
        dtItens = New DataTable
        dtItens.Columns.Add("pasta_id", GetType(Integer))
        dtItens.Columns.Add("proc_legacy", GetType(LegacyData.Proc))
        dtItens.Columns.Add("numero", GetType(String))
        dtItens.Columns.Add("volumes", GetType(Integer))
        dtItens.Columns.Add("apensamento", GetType(String))
        dtItens.Columns.Add("observacoes", GetType(String))
        DataGridViewProcessos.AutoGenerateColumns = True
        DataGridViewProcessos.DataSource = dtItens
    End If
End Sub
Private Sub DataGridViewProcessos_DataSourceChanged(sender As Object, e As EventArgs) _
            Handles DataGridViewProcessos.DataSourceChanged
    If TableViewProcessos.DataSource IsNot Nothing Then
        DataGridViewProcessos.Columns("pasta_id").Visible = False
        DataGridViewProcessos.Columns("proc_legacy").Visible = False
    End If
End Sub

2 个答案:

答案 0 :(得分:0)

您的ParentChanged事件处理程序执行此操作:

If TableViewProcessos.DataSource Is Nothing Then
    '...
    DataGridViewProcessos.DataSource = dtItens
End If

然后你的DataSourceChanged事件处理程序执行此操作:

If TableViewProcessos.DataSource IsNot Nothing Then

如果另一个DataSource,则只设置一个Nothing,因此在其他事件处理程序中不会是Not Nothing

无论如何,在设置DataSourceChanged属性时会引发DataSource事件。该属性的setter执行许多任务,其中一个任务是引发该事件。很可能是在执行创建列的任务之前引发了事件,这使得在DataSourceChanged事件处理程序中没有要访问的列完全合理。在实际设置DataSource之后立即隐藏代码中的列可能更有意义。

答案 1 :(得分:0)

好的,我自己解决了这个问题:

Private dtItens As DataTable
Private Sub DataGridViewProcessos_ParentChanged(sender As Object, e As EventArgs) Handles DataGridViewProcessos.ParentChanged
    If DataGridViewProcessos.DataSource Is Nothing Then
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .DataPropertyName = "pasta_id",
                .Name = "pasta_id",
                .Visible = False})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .DataPropertyName = "proc_legacy",
                .Name = "proc_legacy",
                .Visible = False})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells,
                .DataPropertyName = "numero",
                .HeaderText = "Número",
                .Name = "numero",
                .ReadOnly = True})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells,
                .DataPropertyName = "volumes",
                .HeaderText = "Volumes",
                .Name = "volumes"})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewComboBoxColumn With {
                .AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells,
                .DataPropertyName = "apensamento",
                .DataSource = Apensos,
                .HeaderText = "Apenso a",
                .Name = "apensamento"})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
                .DataPropertyName = "observacoes",
                .HeaderText = "Observações",
                .Name = "observacoes"})
        DataGridViewProcessos.Columns.Add(
            New DataGridViewTextBoxColumn With {
                .DataPropertyName = "principal",
                .Name = "principal",
                .Visible = False})
        dtItens = New DataTable
        dtItens.Columns.Add("pasta_id", GetType(Integer))
        dtItens.Columns.Add("proc_legacy", GetType(SicForm.Processo))
        dtItens.Columns.Add("numero", GetType(String))
        dtItens.Columns.Add("volumes", GetType(Integer))
        dtItens.Columns.Add("apensamento", GetType(String))
        dtItens.Columns.Add("observacoes", GetType(String))
        dtItens.Columns.Add("principal", GetType(Boolean))
        DataGridViewProcessos.DataSource = dtItens
    End If
End Sub

看起来,DataGridView必须具有此前设计的列,因为它始终可以根据DataTable设置为其DataSource自动设置其列。

我无法理解为什么,因为我无法理解这篇文章的痒痒,并且从未露出解释原因......叹息。无论如何,我解决了我的问题,我感谢所有给他任何时间努力帮助的人。 : - )