Como puedo crear un filtro usando un textbox en este datagrid, para buscar por nombre, apellido o país.
Public Class Form1
Dim WithEvents dtgw As New DataGridView
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Me.Controls.Add(dtgw)
Me.Width = 510
With dtgw
.Size = New Size(500, 200)
.ColumnCount = 3
.Columns.Item(0).Name = "Nombre"
.Columns.Item(1).Name = "Apellido"
.Columns.Item(2).Name = "País"
End With
dtgw.Rows.Add("Julio", "Hernández", "Puerto Rico")
dtgw.Rows.Add("Alicia", "Casanova", "España")
dtgw.Rows.Add("Manuel", "Pérez", "México")
End Sub
End Class
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.
Public Class Form1
Dim WithEvents dtgw As New DataGridView
Dim WithEvents bSearch As New Button
Dim WithEvents txtBox As New TextBox
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
With Me
.Controls.AddRange({dtgw, bSearch, txtBox})
.Width = 510
With .dtgw
.Size = New Size(500, 150)
.ColumnCount = 3
.Columns.Item(0).Name = "Nombre"
.Columns.Item(1).Name = "Apellido"
.Columns.Item(2).Name = "País"
End With
bSearch.Location = New Point(155, 160)
bSearch.Text = "Buscar"
txtBox.Location = New Point(50, 160)
txtBox.Width = 100
.dtgw.Rows.Add("Julio", "Hernández", "Puerto Rico")
.dtgw.Rows.Add("Alicia", "Casanova", "España")
.dtgw.Rows.Add("Manuel", "Pérez", "México")
End With
End Sub
Private Sub bSearch_Click(sender As Object, e As EventArgs) Handles bSearch.Click
dtgw.ClearSelection()
For Each Column As DataGridViewColumn In dtgw.Columns
For Each row As DataGridViewRow In dtgw.Rows
Try
If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
row.Cells(Column.Index).Selected = True
End If
Catch ex As Exception
End Try
Next
Next
End Sub
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
With .dtgw
.Size = New Size(500, 150)
.AllowUserToAddRows = False '<-------
.ColumnCount = 3
.Columns.Item(0).Name = "Nombre"
.Columns.Item(1).Name = "Apellido"
.Columns.Item(2).Name = "País"
End With
.....
Private Sub bSearch_Click(sender As Object, e As EventArgs) Handles bSearch.Click
dtgw.ClearSelection()
For Each Column As DataGridViewColumn In dtgw.Columns
For Each row As DataGridViewRow In dtgw.Rows
If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
row.Cells(Column.Index).Selected = True
End If
Next
Next
End Sub
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
Cita de: 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
Private Sub txtBox_TextChanged(sender As Object, e As EventArgs) Handles txtBox.TextChanged
dtgw.ClearSelection()
Dim IndexFilaEncontrada As Integer = Nothing
For Indice As Integer = 0 To dtgw.Rows.Count - 1
dtgw.Rows(Indice).Visible = True
Next
For Each Column As DataGridViewColumn In dtgw.Columns
For Each row As DataGridViewRow In dtgw.Rows
Try
If txtBox.Text.ToString.ToLower.Equals(row.Cells(Column.Index).Value.ToString.ToLower) Then
IndexFilaEncontrada = CInt(row.Index)
For Indice As Integer = 0 To dtgw.Rows.Count - 1
If Not Indice = IndexFilaEncontrada Then
dtgw.Rows(Indice).Visible = False
End If
Next
End If
Catch ex As Exception
End Try
Next
Next
End Sub
Cita de: bybaal en 9 Abril 2017, 01:15 AMRealmente 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.
Public NotInheritable Class Form1 : Inherits Form
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
Me.TriggerFindText(DirectCast(sender, TextBox), Me.DataGridView1)
End Sub
Private Sub TriggerFindText(ByVal tb As TextBox, ByVal dgv As DataGridView)
' Cuando se dispara el evento TextBox.TextChanged, guardamos el texto actual en una variable,
' esperamos 300-500 ms approx. y verificamos si el texto sigue siendo el mismo o ha cambiado.
' De esta manera evitamos realizar búsquedas indeseadas (términos de búsqueda incompletos) mientras el usuario está escribiendo.
' Util también si tenemos miles de filas en el datagridview, para evitar bloqueos en el thread de la UI.
' Como es evidente, esta metodología está pensada para una búsqueda en "tiempo real";
' Si prefieres iniciar la búsqueda solamente cuando se presione la tecla "Enter" entonces esta metodología no tienes por que usarla...
Dim t As New Task(
Sub()
Dim oldText As String = tb.Text
Dim newText As String
Thread.Sleep(400)
newText = tb.Text
If String.IsNullOrEmpty(newText) Then
ShowAllRowsInDataGridView(dgv)
ElseIf (oldText = newText) Then
FindTextInDataGridView(dgv, tb.Text, StringComparison.OrdinalIgnoreCase)
Else ' (oldText <> newText)
' El texto ha cambiado, así que no hacemos nada.
End If
End Sub)
t.Start()
End Sub
Friend Shared Sub ShowAllRowsInDataGridView(ByVal dgv As DataGridView)
If (dgv.InvokeRequired) Then
dgv.Invoke(New Action(Sub() ShowAllRowsInDataGridView(dgv)))
End If
dgv.SuspendLayout()
For Each row As DataGridViewRow In dgv.Rows
If Not (row.IsNewRow) Then
row.Visible = True
End If
Next row
dgv.ResumeLayout(performLayout:=True)
End Sub
Friend Shared Sub FindTextInDataGridView(ByVal dgv As DataGridView, ByVal str As String, ByVal stringComparison As StringComparison)
If (dgv.InvokeRequired) Then
dgv.Invoke(New Action(Sub() FindTextInDataGridView(dgv, str, stringComparison)))
End If
Dim cellContainsFunc As Func(Of DataGridViewCell, String, Boolean) =
Function(ByVal cell As DataGridViewCell, s As String)
If (cell.Value IsNot Nothing) Then
Return (cell.Value.ToString().IndexOf(s, stringComparison) <> -1)
Else
Return False
End If
End Function
Dim indices As IEnumerable(Of Integer) =
(From row As DataGridViewRow In dgv.Rows
Where row.Cells.Cast(Of DataGridViewCell).Any(Function(x As DataGridViewCell) cellContainsFunc(x, str))
Select row.Index)
dgv.SuspendLayout()
dgv.ClearSelection()
For Each row As DataGridViewRow In dgv.Rows
If Not (row.IsNewRow) Then
row.Visible = indices.Contains(row.Index)
End If
Next row
dgv.ResumeLayout(performLayout:=True)
End Sub
End Class
¡Saludos!
Gracias Elektro y todos los que me ayudaron. Justamente es esto lo que estaba buscando.