Vb.net 过滤不带数据源的DatagridView

Vb.net 过滤不带数据源的DatagridView,vb.net,filter,datagridview,restsharp,Vb.net,Filter,Datagridview,Restsharp,我试图通过文本框通过代码过滤手动加载的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", D

我试图通过文本框通过代码过滤手动加载的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

我通过以下方式实现了这一目标。我已经创建了一个带有此gridview所需字段的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方法,而是用接收到的数据填充datatable

    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全局分配为DataGridView的数据源

    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
如果Me.Txt\u buscar.Text.Length>2,则
Dim campo作为字符串=“cancion”
尝试
Dim筛选器为String=String.Format(“[{0}]如“{1}%”,campo,Me.Txt_-buscar.Text)
GridTable.DefaultView.RowFilter=过滤器
特例
MessageBox.Show(“Coño,no puedo buscar!!!Vaya mierda de programmador estáhecho el Zeko!!!”&vbCrLf&vbCrLf&“Error:”&ex.Message,“Coño!!!”,MessageBoxButtons.OK,MessageBoxIcon.Error)
结束尝试
ElseIf Me.Txt_buscar.Text.Length<2则
DirectCast(Me.Dgv_canciones.DataSource,DataTable).DefaultView.RowFilter=String.Empty
如果结束
在这里,我给大家留下完整的修正和功能代码

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
公共类Frm\u cancions
Dim GridTable作为DataTable
私有子Frm_Canciones_Load(发送方作为对象,e作为事件参数)处理MyBase.Load
Me.Dgv_canciones.Rows.Clear()
Dim请求作为新请求(“canciones”,DataFormat.Json)
ClienteRest.Cabeceras(请求)
Dim响应=clientest.cliente.Get(请求)
将respuesta作为新的JObject(CType(jsoninvert.DeserializeObject(response.Content),JObject))
Dim dt作为新数据表
添加(“id”,GetType(字符串))
添加(“cancion”,GetType(字符串))
Add(“duracion”,GetType(String))
添加(“url”,GetType(字符串))
Add(“archivo”,GetType(String))
对于响应中的JToken标记,选择token(“数据”)
Dim song As Cancion=token.ToObject(属于Cancion)
dt.Rows.Add(song.id.ToString,song.getitulocompleto().ToString,song.duracion.ToString,song.url.ToString,song.archivo.ToString)
下一个
Me.GridTable=dt
Me.Dgv_canciones.DataSource=Me.GridTable
端接头
私有子Txt_buscar_TextChanged(发送者作为对象,e作为事件参数)处理Txt_buscar.TextChanged
如果Me.Txt_buscar.Text.Length>2,则
Dim campo作为字符串=“cancion”
尝试
Dim筛选器为String=String.Format(“[{0}]如“{1}%”,campo,Me.Txt_-buscar.Text)
GridTable.DefaultView.RowFilter=过滤器
特例
MessageBox.Show(“Coño,no puedo buscar!!!Vaya mierda de programmador estáhecho el Zeko!!!”&vbCrLf&vbCrLf&“Error:”&ex.Message,“Coño!!!”,MessageBoxButtons.OK,MessageBoxIcon.Error)
结束尝试
ElseIf Me.Txt_buscar.Text.Length<2则
DirectCast(Me.Dgv_canciones.DataSource,DataTable).DefaultView.RowFilter=String.Empty
如果结束
端接头
私有子Frm_Canciones_KeyDown(发送方作为对象,e作为KeyEventArgs)处理MyBase.KeyDown
如果e.KeyCode=Keys.Escape,则
我
如果结束
端接头
私有子Dgv_canciones_CellDoubleClick(发件人作为对象,e作为DataGridViewCellEventArgs)处理Dgv_canciones.CellDoubleClick
如果(Me.Dgv_canciones.CurrentRow.Index+1)

End Class

您从未将数据表设置为DGV的数据源,因此
CType(Me.DGV_canciones.DataSource,DataTable)
不会给您带来太多的好处,您已经知道了。您没有显示JSON,但也有可能您可以直接反序列化到DataTable。问题是,如果datagridview是由带有insert方法的循环填充的,并且没有关联的数据源或DataTable,那么如何在文本框中仅显示与插入的文本匹配的行。使用可以描述所需值的类对象填充
绑定列表
要在DGV中显示,请使用BindingList作为BindingSource的数据源,将BindingSource设置为DGV的数据源。使用BindingSource方法对DGV进行筛选、排序等。或者,填写一个数据表,它提供了相同的工具。控件只是表示器(表示数据的工具),而不是数据存储/处理工具。如果要高效地工作,需要将数据与视图分离。否则,就需要不断地寻找新的黑客。谢谢,@Jimi。我已经用你的最后一个例子做了。我刚刚发布了我应用的解决方案,它是100%功能性的。非常感谢你的贡献。好的。有一件事你必须改变:你不需要或者不想创建一个新的数据视图。删除此项:
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
。或者,由于您存储了数据表,
GridTable.DefaultView.RowFilter=filter
,这是同样的事情,因为您指向的是同一个对象。好吧,最后我选择了根据您的建议改进代码<代码>变暗过滤器为S