none
Resaltar resultados de búsqueda en DataGrid RRS feed

  • Pregunta

  • Buenas tardes quisiera saber si es posible resaltar los resultados de búsqueda en la barra de desplazamiento vertical de un DataGrid tal como se hace en algunas aplicaciones como los exploradores web.Busqueda Explorardor Web

    Jesus IZC

    martes, 17 de mayo de 2016 20:23

Respuestas

  • Hola Jesus:

     Tomando el codigo de ejemplo del articulo que te sugiero te prepare un ejemplo en donde basicamente se requieren de dos controles.

     1. Un control TextBox del cual utilizaremos su evento TextChange para lanzar la busqueda sobre el control DataGridView

     2. Un control DataGridView cargado con datos, en el ejemplo que pondre mas abajo cargo este objeto por medio de una lista de clases, tu puedes utilizar el origen que quieras.

    Codigo:

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim productos As New List(Of Producto)
            For i As Integer = 0 To 50
                Dim item As New Producto()
                item.ProductoId = ++i
                item.Nombre = "nombre del producto " & i
                item.Precio = (15 / 2) * i
                productos.Add(item)
            Next
    
            DataGridView1.DataSource = productos
        End Sub
    
        Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
            'If there is no search string, no rows, or nothing in this cell, then get out. 
            If txt_SearchFilter.Text = String.Empty Then Return
            If (e.Value Is Nothing) Then Return
            If e.RowIndex < 0 Or e.ColumnIndex < 0 Then Return
    
            e.Handled = True
            e.PaintBackground(e.CellBounds, True)
    
            'Get the value of the text in the cell, and the search term. Work with everything in lowercase for more accurate highlighting
            Dim str_SearchTerm As String = txt_SearchFilter.Text.Trim.ToLower
            Dim str_CellText As String = DirectCast(e.FormattedValue, String).ToLower
    
            'Create a list of the character ranges that need to be highlighted. We need to know the start index and the length
            Dim HLRanges As New List(Of CharacterRange)
            Dim SearchIndex As Integer = str_CellText.IndexOf(str_SearchTerm)
            Do Until SearchIndex = -1
                HLRanges.Add(New CharacterRange(SearchIndex, str_SearchTerm.Length))
                SearchIndex = str_CellText.IndexOf(str_SearchTerm, SearchIndex + str_SearchTerm.Length)
            Loop
    
            ' We also work with the original cell text which is has not been converted to lowercase, else the sizes are incorrect
            str_CellText = DirectCast(e.FormattedValue, String)
    
            ' Choose your colours. A different colour is used on the currently selected rows
            Dim HLColour As SolidBrush
            If ((e.State And DataGridViewElementStates.Selected) <> DataGridViewElementStates.None) Then
                HLColour = New SolidBrush(Color.DarkGoldenrod)
            Else
                HLColour = New SolidBrush(Color.BurlyWood)
            End If
    
            'Loop through all of the found instances and draw the highlight box
            For Each HLRange In HLRanges
    
                ' Create the rectangle. It should start just underneath the top of the cell, and go to just above the bottom
                Dim HLRectangle As New Rectangle()
                HLRectangle.Y = e.CellBounds.Y + 2
                HLRectangle.Height = e.CellBounds.Height - 5
    
                ' Determine the size of the text before the area to highlight, and the size of the text to highlight. 
                ' We need to know the size of the text before so that we know where to start the highlight rectangle
                Dim TextBeforeHL As String = str_CellText.Substring(0, HLRange.First)
                Dim TextToHL As String = str_CellText.Substring(HLRange.First, HLRange.Length)
                Dim SizeOfTextBeforeHL As Size = TextRenderer.MeasureText(e.Graphics, TextBeforeHL, e.CellStyle.Font, e.CellBounds.Size)
                Dim SizeOfTextToHL As Size = TextRenderer.MeasureText(e.Graphics, TextToHL, e.CellStyle.Font, e.CellBounds.Size)
    
                'Set the width of the rectangle, a little wider to make the highlight clearer
                If SizeOfTextBeforeHL.Width > 5 Then
                    HLRectangle.X = e.CellBounds.X + SizeOfTextBeforeHL.Width - 6
                    HLRectangle.Width = SizeOfTextToHL.Width - 6
                Else
                    HLRectangle.X = e.CellBounds.X + 2
                    HLRectangle.Width = SizeOfTextToHL.Width - 6
                End If
    
                'Paint the highlight area
                e.Graphics.FillRectangle(HLColour, HLRectangle)
            Next
    
            'Paint the rest of the cell as usual
            e.PaintContent(e.CellBounds)
        End Sub
    
        Private Sub txt_SearchFilter_TextChanged(sender As Object, e As EventArgs) Handles txt_SearchFilter.TextChanged
            'Lanzamos la busqueda por cada cambio ocurrido en el TextBox
            DataGridView1.Refresh()
        End Sub
    End Class
    
    Public Class Producto
        Property ProductoId() As Integer
        Property Nombre() As String
        Property Precio() As Decimal
    End Class
    

     Formulario de ejemplo:

     Tecleamos algún valor en el control TextBox:

     Como veras se están remarcando todas las celdas que contienen el valor ingresado en el control TextBox, espero sea lo que necesitas.


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 18 de mayo de 2016 20:29

Todas las respuestas

  • Hola:
    > Los resultados de una busqueda (datatable) ¿en la barra de desplazamiento vertical de un DataGridView? <

    Los resultados de una busqueda (datatable) se cargan en el DataGridView y este mostrara las barras de desplazamiento si son necesarias.

    Un saludo desde Bilbo
    Carlos
    martes, 17 de mayo de 2016 21:00
  • Hola Carlos

    Al parecer no me explique bien, en la imagen se muestra claramente lo que busco solucionar; obviamente cargo un listado grande en un DataGrid, y posteriormente hago una busqueda en ese listado y suponiendo que la búsqueda me muestre varias coincidencias marcarlo en la barra de desplazamiento vertical como se muestra en la imagen para que así el usuario se desplace específicamente a esa región del listado.

    Saludos.


    Jesus IZC

    miércoles, 18 de mayo de 2016 15:55
  • Hola Jesus IZC,

    La verdad no creo que se pueda hacer, necesariamente quieres hacer ese tipo de "ayuda" al usuario? Porque podrías cambiar de color a las celdas que tengan una coincidencia, así mientras vaya scroleando el usuario se daría cuenta de cuales son los resultados de su consulta.

    O si estás usando el DataSource de tu DataGridView solo mostrar las coincidencias y las que no coincidan ocultarlas.

    En fin, solo es cuestión de saber si tu requerimiento puede variar.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    miércoles, 18 de mayo de 2016 17:13
  • Hola:

     ¿La aplicación que estas desarrollando es Web?, lo pregunto porque mencionas el control DataGrid, si la idea es facilitarle la vida al usuario, lo mas sencillo sera filtrar el DataGrid por cada elemento que coincida con el parámetro indicado (podría ser desde un TextEditor) esto por que si el control contiene una cantidad considerable de registros o este paginado no podrás resaltar todas las coincidencias (en el determinado caso de poder esto que deseas) en cambio si aplicas el filtro podrás ir reduciendo la cantidad de información a analizar sin mencionar que entre mas información podrás hasta dar con el elemento deseado directamente.

     Sin mas información de tu parte es todo lo que podría aportar.


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 18 de mayo de 2016 17:45
  • Hola JC y Jose Luis

    Proyecto de Windows Forms

    Gracias por sus sugerencias, las búsqueda si la realizo y marco todas las coincidencias sin problemas, solo queria saber si era posible añadir esta característica como un plus, pero veo que no es posible o es algo no habitual en este entorno, solo en el entorno web.

    Seguiré intentando a ver si es posible mil gracias.

    Saludos


    Jesus IZC

    miércoles, 18 de mayo de 2016 18:39
  • Hola Jesús:

     Claro que es posible, que no lo hayamos echo personalmente no significa que alguien mas no lo haya echo, te dejo un articulo en donde se menciona una técnica para lograr esto que deseas:

    VB.net: Highlighting a search term in a DataGridView

    Para lograrlo tendrás que valerte de un control TextBox para realizar la búsqueda.


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 18 de mayo de 2016 19:53
  • Hola Jesus:

     Tomando el codigo de ejemplo del articulo que te sugiero te prepare un ejemplo en donde basicamente se requieren de dos controles.

     1. Un control TextBox del cual utilizaremos su evento TextChange para lanzar la busqueda sobre el control DataGridView

     2. Un control DataGridView cargado con datos, en el ejemplo que pondre mas abajo cargo este objeto por medio de una lista de clases, tu puedes utilizar el origen que quieras.

    Codigo:

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim productos As New List(Of Producto)
            For i As Integer = 0 To 50
                Dim item As New Producto()
                item.ProductoId = ++i
                item.Nombre = "nombre del producto " & i
                item.Precio = (15 / 2) * i
                productos.Add(item)
            Next
    
            DataGridView1.DataSource = productos
        End Sub
    
        Private Sub DataGridView1_CellPainting(sender As Object, e As DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
            'If there is no search string, no rows, or nothing in this cell, then get out. 
            If txt_SearchFilter.Text = String.Empty Then Return
            If (e.Value Is Nothing) Then Return
            If e.RowIndex < 0 Or e.ColumnIndex < 0 Then Return
    
            e.Handled = True
            e.PaintBackground(e.CellBounds, True)
    
            'Get the value of the text in the cell, and the search term. Work with everything in lowercase for more accurate highlighting
            Dim str_SearchTerm As String = txt_SearchFilter.Text.Trim.ToLower
            Dim str_CellText As String = DirectCast(e.FormattedValue, String).ToLower
    
            'Create a list of the character ranges that need to be highlighted. We need to know the start index and the length
            Dim HLRanges As New List(Of CharacterRange)
            Dim SearchIndex As Integer = str_CellText.IndexOf(str_SearchTerm)
            Do Until SearchIndex = -1
                HLRanges.Add(New CharacterRange(SearchIndex, str_SearchTerm.Length))
                SearchIndex = str_CellText.IndexOf(str_SearchTerm, SearchIndex + str_SearchTerm.Length)
            Loop
    
            ' We also work with the original cell text which is has not been converted to lowercase, else the sizes are incorrect
            str_CellText = DirectCast(e.FormattedValue, String)
    
            ' Choose your colours. A different colour is used on the currently selected rows
            Dim HLColour As SolidBrush
            If ((e.State And DataGridViewElementStates.Selected) <> DataGridViewElementStates.None) Then
                HLColour = New SolidBrush(Color.DarkGoldenrod)
            Else
                HLColour = New SolidBrush(Color.BurlyWood)
            End If
    
            'Loop through all of the found instances and draw the highlight box
            For Each HLRange In HLRanges
    
                ' Create the rectangle. It should start just underneath the top of the cell, and go to just above the bottom
                Dim HLRectangle As New Rectangle()
                HLRectangle.Y = e.CellBounds.Y + 2
                HLRectangle.Height = e.CellBounds.Height - 5
    
                ' Determine the size of the text before the area to highlight, and the size of the text to highlight. 
                ' We need to know the size of the text before so that we know where to start the highlight rectangle
                Dim TextBeforeHL As String = str_CellText.Substring(0, HLRange.First)
                Dim TextToHL As String = str_CellText.Substring(HLRange.First, HLRange.Length)
                Dim SizeOfTextBeforeHL As Size = TextRenderer.MeasureText(e.Graphics, TextBeforeHL, e.CellStyle.Font, e.CellBounds.Size)
                Dim SizeOfTextToHL As Size = TextRenderer.MeasureText(e.Graphics, TextToHL, e.CellStyle.Font, e.CellBounds.Size)
    
                'Set the width of the rectangle, a little wider to make the highlight clearer
                If SizeOfTextBeforeHL.Width > 5 Then
                    HLRectangle.X = e.CellBounds.X + SizeOfTextBeforeHL.Width - 6
                    HLRectangle.Width = SizeOfTextToHL.Width - 6
                Else
                    HLRectangle.X = e.CellBounds.X + 2
                    HLRectangle.Width = SizeOfTextToHL.Width - 6
                End If
    
                'Paint the highlight area
                e.Graphics.FillRectangle(HLColour, HLRectangle)
            Next
    
            'Paint the rest of the cell as usual
            e.PaintContent(e.CellBounds)
        End Sub
    
        Private Sub txt_SearchFilter_TextChanged(sender As Object, e As EventArgs) Handles txt_SearchFilter.TextChanged
            'Lanzamos la busqueda por cada cambio ocurrido en el TextBox
            DataGridView1.Refresh()
        End Sub
    End Class
    
    Public Class Producto
        Property ProductoId() As Integer
        Property Nombre() As String
        Property Precio() As Decimal
    End Class
    

     Formulario de ejemplo:

     Tecleamos algún valor en el control TextBox:

     Como veras se están remarcando todas las celdas que contienen el valor ingresado en el control TextBox, espero sea lo que necesitas.


    Saludos desde Monterrey, Nuevo León, México!!!

    miércoles, 18 de mayo de 2016 20:29