|
En este artículo te explico estos conceptos: - Cómo hacer auto completar usando el contenido de un TextBox y buscando en un DataTable - Buscar en las columnas de un control DataGrid
¿Qué hace este ejemplo?
Te explico lo que he hecho para que lo entiendas bien y puedas adaptarlo a tus necesidades.
En este ejemplo uso una base de datos de SQL Server 2005, pero sirve para cualquier tipo de base de datos, solo que tendrás que modificar la cadena de conexión y el tipo del "DataAdapter" usado para acceder a los datos.
Esa base de datos se llama Pruebas y tiene una tabla llamada Clientes.
Esa tabla tiene varios campos, pero en este ejemplo solo se usan dos: Nombre yApellidos.
En el formulario de ejemplo uso estos controles: (ver la figura 1)
 Figura 1. El formulario en modo de diseño Una etiqueta, una caja de textos llamada txtNombreBuscar, un ListView para mostrar lo que se vaya encontrando conforme escribes, esa lista se llama listViewNombres. También hay un control de tipo DataGrid en el que se mostrarán los datos que hemos leído de la base de datos, ese control se llama dtgNombres.
Cuando escribas algo en la caja de textos, se busca en la base de datos (en realidad en el contenido del DataTable que hemos cargado al iniciar la aplicación), y se van mostrando los datos en la lista. En la figura 2 puedes ver un ejemplo al escribir las letras Pere
 Figura 2. La aplicación en ejecución ¿Qué se necesita para hacer esto?Nota:Junto al texto, te muestro el código de Visual Basic, el de C# lo tienes abajo, pero creo que no te será complicado "adivinar" que es lo que tienes que escribir en cada momento. Aparte de los controles que te he comentado, tendrás que definir un objeto del tipo DataTable que será donde estén los datos que hay en la tabla de Clientes:
' El DataTable lo necesitamos a nivel del formulario
Private dt As DataTable
Para obtener esos datos y llenar la tabla, necesitas un DataAdapter, que dependiendo de si accedes a una base de datos de Access o de SQL Server (o de cualquier otro tipo), tendrás que definirlo de la forma adecuada, en este ejemplo uso una base de datos de SQL Server, por tanto, el "adaptador" que uso es del tipoSqlDataAdapter. Y como es posible que use otras cosas (que en este caso no las uso), lo mejor es añadir una importación al espacio de nombres en el que está definido el adaptador:
Imports System.Data
Imports System.Data.SqlClient
El adaptador (recuerda que la base es de SQL Server), lo declaramos de esta forma:
' El adapatador para obtener los datos
Private da As SqlDataAdapter
También necesitas la cadena de conexión a la base de datos, en mi caso, la base de datos está en la instancia de SQLEXPRESS, por tanto, uso esta cadena:
' La cadena de conexión
Private conexion As String = _
"Data Source = (local)\SQLEXPRESS; " & _
"Initial Catalog=PruebasGuille; " & _
"Integrated Security=true"
La cadena de selección (la que indica que datos debemos traer de la base de datos), es muy simple: traemos todos los nombres y apellidos de la tabla Clientes:
' La cadena de selección
' los datos que traeremos de la base de datos.
Private seleccion As String = _
"SELECT Nombre, Apellidos FROM Clientes"
Cargar los datos
Una vez que tenemos todas las variables definidas, (en realidad solo es necesario definir el DataTable a nivel de formulario), en el evento Load del formulario cargamos el DataTable con los datos:
Private Sub Form1_Load( _
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles MyBase.Load
Me.txtNombreBuscar.Text = ""
da = New SqlDataAdapter(seleccion, conexion)
dt = New DataTable
da.Fill(dt)
Me.dtgNombres.DataSource = dt
iniciando = False
End Sub
Fíjate en dos detalles del código anterior:
- Asigno una cadena vacía a la caja de textos. Esto es por si tenía algo escrito.
- Estoy usando una variable que he declarado a nivel de formulario para saber si estoy iniciando los datos o no. Al definirla le asigno un valor verdadero, y cuando se termina el código del formulario le asigno un valor falso.
Buscar los datos según lo escrito
Esto lo hago porque en el evento TextChanged de la caja de textos hago la comprobación de si los apellidos escritos están en la tabla, y como resulta que al iniciarse el formulario (en el constructor), si has escrito algo en el diseñador de formularios, eso que hayas escrito se va a asignar a la propiedad Text de la caja de textos, y cuando el código de asignación se ejecute, se va a producir el eventoTextChanged, y si se produce ese evento antes de que todo esté "inicializado", pues... tendremos un error...
Para que lo comprendas mejor, te muestro el código del evento TextChanged de la caja de textos, que es el que se encarga de hacer la búsqueda en los datos que tenemos en el objeto DataTable (dt):
ByVal sender As Object, _
ByVal e As EventArgs) _
Handles txtNombreBuscar.TextChanged
If iniciando Then Exit Sub
' Buscar en el DataTable usando el método Select
' que es como un filtro WHERE en una cadena de selección.
' El resultado se devuelve como un array de tipo DataRow
Dim filas() As DataRow
' Si solo quieres mostrar los que empiecen por lo escrito.
' Al escribir "s" se buscarán los que empiecen por esa letra.
filas = dt.Select("Apellidos LIKE '" & txtNombreBuscar.Text & "%'")
' Borrar los elementos anteriores
Me.listViewNombres.Items.Clear()
' Si hay datos, mostrar los apellidos
If filas.Length > 0 Then
' Recorrer cada fila y mostrar los apellidos
For Each dr As DataRow In filas
Me.listViewNombres.Items.Add( _
dr("Apellidos").ToString & ", " & _
dr("Nombre").ToString)
Next
End If
End Sub
Fíjate que lo primero que hago en ese evento es comprobar si el valor de la variable iniciando es verdadero, y en caso de que así sea, simplemente "me voy" y no hago nada de nada.
Como puedes imaginar (además de porque ya te lo he dicho), esa variable está definida de esta forma (con idea de que inicialmente tenga un valor verdadero):
' Para evitar re-entradas en el código
Private iniciando As Boolean = True
Buscar en el campo Apellidos con las letras en cualquier posición
El "truco" de todo esto está en la forma de usar el método Select del objetoDataTable.
Ese método espera una expresión al estilo de la que usaríamos con WHERE en una consulta de SQL, por tanto, podemos usar lo mismo que en esa cláusula WHERE. En el código anterior, lo que le digo que haga es:
Buscar todas las filas en las que el campo Apellidos "empiece" con el texto indicado.
Que traducido al lenguaje que entiende el método Select es: Apellidos LIKE 'cadena'
Y como le hemos puesto un signo de porcentaje al final, le estamos diciendo que busque lo que haya en la caja de textos y si en el campo Apellidos hay más cosas después de lo indicado, pues que lo de por bueno.
Por tanto, si tenemos varios datos de apellidos que empiezan por la letra eme y escribimos una "R", se mostrarán todos los que coincidan, que es lo que puedes ver en la figura 2.
Pero si en vez de usar el código mostrado antes, usas este otro:
filas = dt.Select("Apellidos LIKE '%" & txtNombreBuscar.Text & "%'")Como estamos usando los caracteres comodines antes y después de lo que se escriba, el resultado al escribir la letra " R" será el que ves en la figura 3, que si te fijas en la lista, hay más de los 2 datos que mostró el primer código que usé para la captura de la figura 2, ya que se encuentran todos los que tenga alguna letra R en los apellidos, además de que no se hace distinción de si están en mayúsculas o minúsculas.
 Figura 3. Sin tener en cuenta donde está lo escrito
Y esto es todo... espero que te de una idea de cómo hacerlo y que lo sepas adaptar a todas tus necesidades, y como dicen la practica hace al maestro, entonces a practicar que mucha falta me hace jejej ;).
El código para C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// Para evitar re-entradas en el código
private bool iniciando = true;
// El DataTable lo necesitamos a nivel del formulario
private DataTable dt;
// El resto de variables no son necesarias a nivel de formulario
// y pueden estar definidas en el evento Form_Load
// La cadena de conexión
private string conexion =
@"Data Source = (local)\SQLEXPRESS; " +
"Initial Catalog=PruebasGuille; " +
"Integrated Security=true";
// La cadena de selección
// los datos que traeremos de la base de datos.
private string seleccion =
"SELECT Nombre, Apellidos FROM Clientes";
// El adapatador para obtener los datos
private SqlDataAdapter da;
private void Form1_Load(object sender, EventArgs e)
{
this.txtNombreBuscar.Text = "";
da = new SqlDataAdapter(seleccion, conexion);
dt = new DataTable();
da.Fill(dt);
this.dtgNombres.DataSource = dt;
iniciando = false;
}
private void txtNombreBuscar_TextChanged(object sender, EventArgs e)
{
if (iniciando) return;
// Buscar en el DataTable usando el método Select
// que es como un filtro WHERE en una cadena de selección.
// El resultado se devuelve como un array de tipo DataRow
DataRow[] filas;
// Aquí es donde hay que hacer el filtro de cómo buscar
// Usando % ... % no se tiene en cuenta dónde está el apellido escrito
// (puede ser el primero o el segundo)
// Si escribes "s" se buscarán todos los que contengan esa letra.
filas = dt.Select("Apellidos LIKE '%" + txtNombreBuscar.Text + "%'");
// Borrar los elementos anteriores
this.listViewNombres.Items.Clear();
// Si hay datos, mostrar los apellidos
if (filas.Length > 0)
{
// Recorrer cada fila y mostrar los apellidos
foreach (DataRow dr in filas)
{
// También puedes mostrar cualquier otro campo,
// pero siempre que esté en la cadena de selección
// usada al cargar los datos
this.listViewNombres.Items.Add(dr["Apellidos"].ToString() + ", " +
dr["Nombre"].ToString());
}
}
}
private void listViewNombres_SelectedIndexChanged(object sender, EventArgs e)
{
if (iniciando) return;
// Al hacer clic, mostrar el dato
this.txtNombreBuscar.Text = this.listViewNombres.SelectedItem.ToString();
// Buscarlo en el DataGrid (de forma manual, no conozco otra forma...)
// Eliminar las selecciones anteriores
this.dtgNombres.ClearSelection();
// Recorrer las filas para buscar el Apellido indicado
foreach (DataGridRow fila in this.dtgNombres.Rows)
{
// Si es el mismo apellido del textBox
// Curiosamente si no son los mismos datos
// se produce un error de que d.Cells(...) es Nothing
// En realidad de "curioso" no tiene nada,
// es que es la última fila, que está vacía...
if (fila.Cells["Apellidos"].Value == null || fila.Cells == null)
{
break;
}
// Si se quiere tener en cuenta el nombre y los apellidos
int i = this.txtNombreBuscar.Text.IndexOf(",");
if (i > -1)
{
// En este ejemplo, el formato es Apellidos, Nombre
string nombre, apellidos;
apellidos = this.txtNombreBuscar.Text.Substring(0, i).TrimEnd();
nombre = this.txtNombreBuscar.Text.Substring(i + 1).TrimStart();
if (nombre == fila.Cells["Nombre"].Value.ToString()
&& apellidos == fila.Cells["Apellidos"].Value.ToString())
{
// Seleccionamos la fila
this.dtgNombres.Rows[fila.Index].Selected = true;
// nos aseguramos de que sea visible
this.dtgNombres.FirstDisplayedScrollingRowIndex = fila.Index;
break;
}
}
else
{
if (this.txtNombreBuscar.Text == fila.Cells["Apellidos"].Value.ToString())
{
// Seleccionamos la fila
this.dtgNombres.Rows[fila.Index].Selected = true;
// nos aseguramos de que sea visible
this.dtgNombres.FirstDisplayedScrollingRowIndex = fila.Index;
break;
}
}
}
}
}
|