【问题标题】:Filter DatagridView without datasource过滤没有数据源的DatagridView
【发布时间】:2020-09-28 20:58:29
【问题描述】:

我正在尝试通过文本框的代码过滤手动加载的 datagridview。它不起作用,它告诉我 System.NullReferenceException。

Private Sub Frm_Canciones_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.Dgv_canciones.Rows.Clear()

    Dim request As New RestRequest("canciones", DataFormat.Json)

    ClienteRest.Cabeceras(request)

    Dim response = ClienteRest.cliente.Get(request)

    Dim respuesta As New JObject(CType(JsonConvert.DeserializeObject(response.Content), JObject))

    For Each token As JToken In respuesta.SelectToken("data")
        Dim song As Cancion = token.ToObject(Of Cancion)

        Me.Dgv_canciones.Rows.Insert(Me.Dgv_canciones.NewRowIndex, song.id, song.getTituloCompleto(), song.duracion, song.url, song.archivo)
    Next
End Sub

Private Sub Txt_buscar_TextChanged(sender As Object, e As EventArgs) Handles Txt_buscar.TextChanged
    If Me.Txt_buscar.Text.Length > 3 Then
        Dim campo As String = "cancion"

        Try
            CType(Me.Dgv_canciones.DataSource, DataTable).DefaultView.RowFilter = String.Format("[{0}] LIKE '%{1}%'", campo, Me.Txt_buscar.Text)
        Catch ex As Exception
            MessageBox.Show("Error: " & ex.Message, "Error!!!", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End If
End Sub

【问题讨论】:

  • 您从未将 DataTable 设置为 DGV 的数据源,因此 CType(Me.Dgv_canciones.DataSource, DataTable) 不会让您得到太多,正如您已经知道的那样。您没有显示 JSON,但您可以直接反序列化为 DataTable。
  • 问题是,如果datagridview是用insert方法循环填充的,并且没有关联的数据源或数据表,我怎么能只在文本框中显示与插入的文本匹配的行。
  • 使用可以描述要在 DGV 中显示的值的类对象填充 BindingList<class>,使用 BindingList 作为 BindingSource 的 DataSource,将 BindingSource 设置为 DGV 的 DataSource使用 BindingSource 方法对 DGV 进行过滤、排序等。或者,填写一个提供相同工具的 DataTable。控件只是呈现器(呈现数据的工具),而不是数据存储/处理工具。如果您想有效地工作,您需要将数据与视图分开。否则,就是不断寻找新的hack
  • 谢谢,@Jimi。我已经用你的最后一个例子做到了。我刚刚发布了我应用的解决方案,它是 100% 功能的。非常感谢您的贡献。

标签: vb.net filter datagridview restsharp


【解决方案1】:

我通过以下方式实现了它。我已经创建了一个包含此网格视图所需字段的数据表。虽然,首先我在表单上创建了一个全局 DataTable。

    Dim dt As New DataTable
    dt.Columns.Add("id", GetType(String))
    dt.Columns.Add("cancion", GetType(String))
    dt.Columns.Add("duracion", GetType(String))
    dt.Columns.Add("url", GetType(String))
    dt.Columns.Add("archivo", GetType(String))

在循环中,我没有使用datagridview的insert方法,而是用接收到的数据填充了数据表。

    For Each token As JToken In respuesta.SelectToken("data")
        Dim song As Cancion = token.ToObject(Of Cancion)

        dt.Rows.Add(song.id.ToString, song.getTituloCompleto().ToString, song.duracion.ToString, song.url.ToString, song.archivo.ToString)

    Next

然后,我将生成的 DataTable 映射到表单的全局 DataTable 以供以后使用。我已将 DataTable Global 分配为 DataGridView 的 DataSource。

    Me.GridTable = dt
    Me.Dgv_canciones.DataSource = Me.GridTable

最后,在 TextBox 的 TextChanged 事件中,我放置了一个条件,以便它只搜索用户是否在文本字段中输入了至少 3 个字符。如果您输入的较少,它会加载整个歌曲列表,如果您输入的更多,它会加载搜索结果。

    If Me.Txt_buscar.Text.Length > 2 Then
        Dim campo As String = "cancion"

        Try
            Dim filter As String = String.Format("[{0}] LIKE '%{1}%'", campo, Me.Txt_buscar.Text)
            GridTable.DefaultView.RowFilter = filter
        Catch ex As Exception
            MessageBox.Show("Coño, no puedo buscar!!! Vaya mierda de programador está hecho el Zeko!!!" & vbCrLf & vbCrLf & "Error: " & ex.Message, "Coño!!!", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    ElseIf Me.Txt_buscar.Text.Length < 2 Then
        DirectCast(Me.Dgv_canciones.DataSource, DataTable).DefaultView.RowFilter = String.Empty
    End If

在这里,我将完整的更正和功能代码留给您。

Public Class Frm_Canciones

Dim GridTable As DataTable

Private Sub Frm_Canciones_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Me.Dgv_canciones.Rows.Clear()

    Dim request As New RestRequest("canciones", DataFormat.Json)

    ClienteRest.Cabeceras(request)

    Dim response = ClienteRest.cliente.Get(request)

    Dim respuesta As New JObject(CType(JsonConvert.DeserializeObject(response.Content), JObject))


    Dim dt As New DataTable
    dt.Columns.Add("id", GetType(String))
    dt.Columns.Add("cancion", GetType(String))
    dt.Columns.Add("duracion", GetType(String))
    dt.Columns.Add("url", GetType(String))
    dt.Columns.Add("archivo", GetType(String))

    For Each token As JToken In respuesta.SelectToken("data")
        Dim song As Cancion = token.ToObject(Of Cancion)

        dt.Rows.Add(song.id.ToString, song.getTituloCompleto().ToString, song.duracion.ToString, song.url.ToString, song.archivo.ToString)

    Next

    Me.GridTable = dt
    Me.Dgv_canciones.DataSource = Me.GridTable

End Sub

Private Sub Txt_buscar_TextChanged(sender As Object, e As EventArgs) Handles Txt_buscar.TextChanged
    If Me.Txt_buscar.Text.Length > 2 Then
        Dim campo As String = "cancion"

        Try
            Dim filter As String = String.Format("[{0}] LIKE '%{1}%'", campo, Me.Txt_buscar.Text)
            GridTable.DefaultView.RowFilter = filter
        Catch ex As Exception
            MessageBox.Show("Coño, no puedo buscar!!! Vaya mierda de programador está hecho el Zeko!!!" & vbCrLf & vbCrLf & "Error: " & ex.Message, "Coño!!!", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try

    ElseIf Me.Txt_buscar.Text.Length < 2 Then
        DirectCast(Me.Dgv_canciones.DataSource, DataTable).DefaultView.RowFilter = String.Empty
    End If
End Sub

Private Sub Frm_Canciones_KeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
    If e.KeyCode = Keys.Escape Then
        Me.Close()
    End If
End Sub

Private Sub Dgv_canciones_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles Dgv_canciones.CellDoubleClick
    If (Me.Dgv_canciones.CurrentRow.Index + 1) < Me.Dgv_canciones.Rows.Count Then
        Dim fPrograma As New Frm_programa

        Helpers.currentCancion = New Cancion(Me.Dgv_canciones.Rows.Item(Me.Dgv_canciones.CurrentRow.Index).Cells.Item(0).Value)

        Me.Close()
    End If
End Sub

结束类

【讨论】:

  • 好的。您必须更改一件事:您不需要或不想创建新的 DataView。删除这个:Dim FilterData As New DataView(Me.GridTable)。使用DataTable.DefaultView:例如dim filter = String.Format(...) DirectCast(Dgv_canciones.DataSource, DataTable).DefaultView.RowFilter = filter。要删除过滤器,只需DirectCast(Dgv_canciones.DataSource, DataTable).DefaultView.RowFilter = string.empty。或者,由于您存储了 DataTable,GridTable.DefaultView.RowFilter = filter,这是同一件事,因为您指向的是同一个对象。
  • 好吧,最后我选择根据您的建议改进代码。 Dim filter As String = String.Format ("[{0}] LIKE '% {1}%'", field, Me.Txt_buscar.Text) GridTable.DefaultView.RowFilter = filter
猜你喜欢
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-16
相关资源
最近更新 更多