Foro de elhacker.net

Programación => .NET (C#, VB.NET, ASP) => Mensaje iniciado por: bybaal en 2 Abril 2017, 02:10 am



Título: Filtro en un DataGridView
Publicado por: bybaal en 2 Abril 2017, 02:10 am
Como puedo crear un filtro usando un textbox en este datagrid, para buscar por nombre, apellido o país.

Código
  1. Public Class Form1
  2.  
  3.    Dim WithEvents dtgw As New DataGridView
  4.    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
  5.        Me.Controls.Add(dtgw)
  6.        Me.Width = 510
  7.        With dtgw
  8.            .Size = New Size(500, 200)
  9.            .ColumnCount = 3
  10.            .Columns.Item(0).Name = "Nombre"
  11.            .Columns.Item(1).Name = "Apellido"
  12.            .Columns.Item(2).Name = "País"
  13.        End With
  14.  
  15.        dtgw.Rows.Add("Julio", "Hernández", "Puerto Rico")
  16.        dtgw.Rows.Add("Alicia", "Casanova", "España")
  17.        dtgw.Rows.Add("Manuel", "Pérez", "México")
  18.  
  19.    End Sub
  20. End Class
  21.  
  22.  


Título: Re: Filtro en un DataGridView
Publicado por: okik en 2 Abril 2017, 10:20 am
no entendí muy bien lo que pides. Entiendo que es el típico buscar donde pones un texto, le das a un botón y te selecciona el contenido que buscas.

Código
  1. Public Class Form1
  2.    Dim WithEvents dtgw As New DataGridView
  3.    Dim WithEvents bSearch As New Button
  4.    Dim WithEvents txtBox As New TextBox
  5.    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  6.  
  7.        With Me
  8.            .Controls.AddRange({dtgw, bSearch, txtBox})
  9.            .Width = 510
  10.  
  11.            With .dtgw
  12.                .Size = New Size(500, 150)
  13.                .ColumnCount = 3
  14.                .Columns.Item(0).Name = "Nombre"
  15.                .Columns.Item(1).Name = "Apellido"
  16.                .Columns.Item(2).Name = "País"
  17.            End With
  18.  
  19.            bSearch.Location = New Point(155, 160)
  20.            bSearch.Text = "Buscar"
  21.            txtBox.Location = New Point(50, 160)
  22.            txtBox.Width = 100
  23.  
  24.            .dtgw.Rows.Add("Julio", "Hernández", "Puerto Rico")
  25.            .dtgw.Rows.Add("Alicia", "Casanova", "España")
  26.            .dtgw.Rows.Add("Manuel", "Pérez", "México")
  27.  
  28.  
  29.        End With
  30.    End Sub
  31.  
  32.    Private Sub bSearch_Click(sender As Object, e As EventArgs) Handles bSearch.Click
  33.        dtgw.ClearSelection()
  34.        For Each Column As DataGridViewColumn In dtgw.Columns
  35.            For Each row As DataGridViewRow In dtgw.Rows
  36.                Try
  37.                    If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
  38.                        row.Cells(Column.Index).Selected = True
  39.                    End If
  40.                Catch ex As Exception
  41.                End Try
  42.            Next
  43.        Next
  44.    End Sub
  45. End Class

Si te fijas he usado el Try Catch ya que al haber filas vacías se produciría un error.

Si no quieres filas vacías al final del datagrid establece la propiedad AllowUserToAddRows = False al DataGridView para evitar que el usuario pueda crear nuevas filas  y no se creará una nueva fila vacía. En este caso ya no te hace falta el control de errores Try Catch


Código
  1. With .dtgw
  2.                .Size = New Size(500, 150)
  3.                 .AllowUserToAddRows = False  '<-------
  4.                .ColumnCount = 3
  5.                .Columns.Item(0).Name = "Nombre"
  6.                .Columns.Item(1).Name = "Apellido"
  7.                .Columns.Item(2).Name = "País"
  8.            End With
  9.  
  10.  
  11. .....
  12.  
  13.    Private Sub bSearch_Click(sender As Object, e As EventArgs) Handles bSearch.Click
  14.        dtgw.ClearSelection()
  15.        For Each Column As DataGridViewColumn In dtgw.Columns
  16.            For Each row As DataGridViewRow In dtgw.Rows
  17.                If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
  18.                    row.Cells(Column.Index).Selected = True
  19.                End If
  20.            Next
  21.        Next
  22.    End Sub
  23.  






Título: Re: Filtro en un DataGridView
Publicado por: bybaal en 9 Abril 2017, 01:15 am
Realmente lo que necesitamos es que se oculten las filas que no coinciden con lo buscado y que la búsqueda sea al escribir en el TextBox.

Muchas Gracias


Título: Re: Filtro en un DataGridView
Publicado por: okik en 9 Abril 2017, 14:55 pm
Realmente lo que necesitamos es que se oculten las filas que no coinciden con lo buscado y que la búsqueda sea al escribir en el TextBox.

Muchas Gracias


Código
  1.    Private Sub txtBox_TextChanged(sender As Object, e As EventArgs) Handles txtBox.TextChanged
  2.        dtgw.ClearSelection()
  3.        Dim IndexFilaEncontrada As Integer = Nothing
  4.        For Indice As Integer = 0 To dtgw.Rows.Count - 1
  5.            dtgw.Rows(Indice).Visible = True
  6.        Next
  7.  
  8.        For Each Column As DataGridViewColumn In dtgw.Columns
  9.            For Each row As DataGridViewRow In dtgw.Rows
  10.                Try
  11.                    If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
  12.                        IndexFilaEncontrada = CInt(row.Index)
  13.                        For Indice As Integer = 0 To dtgw.Rows.Count - 1
  14.                            If Not Indice = IndexFilaEncontrada Then
  15.                                dtgw.Rows(Indice).Visible = False
  16.                            End If
  17.                        Next
  18.                    End If
  19.                Catch ex As Exception
  20.                End Try
  21.            Next
  22.        Next
  23.  
  24.    End Sub


Título: Re: Filtro en un DataGridView
Publicado por: Eleкtro en 9 Abril 2017, 17:24 pm
Realmente lo que necesitamos es que se oculten las filas que no coinciden con lo buscado y que la búsqueda sea al escribir en el TextBox.

Aquí abajo te muestro otra alternativa de hacerlo. En caso de que lo uses, adáptalo a tus necesidades.

Código
  1. Public NotInheritable Class Form1 : Inherits Form
  2.  
  3.    Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
  4.  
  5.        Me.TriggerFindText(DirectCast(sender, TextBox), Me.DataGridView1)
  6.  
  7.    End Sub
  8.  
  9.    Private Sub TriggerFindText(ByVal tb As TextBox, ByVal dgv As DataGridView)
  10.  
  11.        ' Cuando se dispara el evento TextBox.TextChanged, guardamos el texto actual en una variable,
  12.        ' esperamos 300-500 ms approx. y verificamos si el texto sigue siendo el mismo o ha cambiado.
  13.        ' De esta manera evitamos realizar búsquedas indeseadas (términos de búsqueda incompletos) mientras el usuario está escribiendo.
  14.        ' Util también si tenemos miles de filas en el datagridview, para evitar bloqueos en el thread de la UI.
  15.  
  16.       ' Como es evidente, esta metodología está pensada para una búsqueda en "tiempo real";
  17.       ' Si prefieres iniciar la búsqueda solamente cuando se presione la tecla "Enter" entonces esta metodología no tienes por que usarla...
  18.  
  19.        Dim t As New Task(
  20.            Sub()
  21.                Dim oldText As String = tb.Text
  22.                Dim newText As String
  23.                Thread.Sleep(400)
  24.  
  25.                newText = tb.Text
  26.                If String.IsNullOrEmpty(newText) Then
  27.                    ShowAllRowsInDataGridView(dgv)
  28.  
  29.                ElseIf (oldText = newText) Then
  30.                    FindTextInDataGridView(dgv, tb.Text, StringComparison.OrdinalIgnoreCase)
  31.  
  32.                Else ' (oldText <> newText)
  33.                    ' El texto ha cambiado, así que no hacemos nada.
  34.  
  35.                End If
  36.  
  37.            End Sub)
  38.  
  39.        t.Start()
  40.  
  41.    End Sub
  42.  
  43.    Friend Shared Sub ShowAllRowsInDataGridView(ByVal dgv As DataGridView)
  44.  
  45.        If (dgv.InvokeRequired) Then
  46.            dgv.Invoke(New Action(Sub() ShowAllRowsInDataGridView(dgv)))
  47.        End If
  48.  
  49.        dgv.SuspendLayout()
  50.        For Each row As DataGridViewRow In dgv.Rows
  51.            If Not (row.IsNewRow) Then
  52.                row.Visible = True
  53.            End If
  54.        Next row
  55.        dgv.ResumeLayout(performLayout:=True)
  56.  
  57.    End Sub
  58.  
  59.    Friend Shared Sub FindTextInDataGridView(ByVal dgv As DataGridView, ByVal str As String, ByVal stringComparison As StringComparison)
  60.  
  61.        If (dgv.InvokeRequired) Then
  62.            dgv.Invoke(New Action(Sub() FindTextInDataGridView(dgv, str, stringComparison)))
  63.        End If
  64.  
  65.        Dim cellContainsFunc As Func(Of DataGridViewCell, String, Boolean) =
  66.            Function(ByVal cell As DataGridViewCell, s As String)
  67.                If (cell.Value IsNot Nothing) Then
  68.                    Return (cell.Value.ToString().IndexOf(s, stringComparison) <> -1)
  69.                Else
  70.                    Return False
  71.                End If
  72.            End Function
  73.  
  74.        Dim indices As IEnumerable(Of Integer) =
  75.            (From row As DataGridViewRow In dgv.Rows
  76.             Where row.Cells.Cast(Of DataGridViewCell).Any(Function(x As DataGridViewCell) cellContainsFunc(x, str))
  77.             Select row.Index)
  78.  
  79.        dgv.SuspendLayout()
  80.        dgv.ClearSelection()
  81.        For Each row As DataGridViewRow In dgv.Rows
  82.            If Not (row.IsNewRow) Then
  83.                row.Visible = indices.Contains(row.Index)
  84.            End If
  85.        Next row
  86.        dgv.ResumeLayout(performLayout:=True)
  87.  
  88.    End Sub
  89.  
  90. End Class

¡Saludos!


Título: Re: Filtro en un DataGridView
Publicado por: bybaal en 10 Abril 2017, 00:58 am
Gracias Elektro y todos los que me ayudaron. Justamente es esto lo que estaba buscando.