Search code examples
vb.netfilterdatagridviewrestsharp

Filter DatagridView without datasource


I'm trying to filter a manually loaded datagridview via code by a textbox. It doesn't work, it tells me 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

Solution

  • I have achieved it in the following way. I have created a datatable with the fields that I need for this gridview. Although, firstly I have created a global DataTable on my form.

        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))
    

    In the loop, instead of using the insert method of the datagridview, I have filled the datatable with the received data.

        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
    

    I have then mapped the resulting DataTable to my form's global DataTable for later use. And I have assigned as DataSource of the DataGridView the DataTable Global.

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

    Finally, in the TextChanged event of the TextBox, I have placed a conditional so that it only searches if the user has typed at least 3 characters in the text field. If you have typed less, it loads the entire list of songs and if you have typed more it loads the search results.

        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
    

    And here I leave you the complete corrected and functional code.

    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
    

    End Class