Professional Documents
Culture Documents
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
ADO.NET
Autos Chevrolet Econmicos, Compactos y Prcticos. Entra y localiza tu distribuidor. www.chevroletcentroamerica.com Abogados de Nicaragua Hgase experto de JustAnswer y gane dinero respondiendo preguntas. www.JustAnswer.es/Trabajo-Abogados Visual SQL to XML Easy to use Data Mapping environment. Try now! www.ecrion.com Licenciatura a Distancia Estudia sin asistir a clase, Licenciatura 100% a Distancia. www.aiu.edu
Introduccin:
En otro artculo anterior (en realidad varios artculos), te expliqu cmo hacer el efecto de auto completar en un control ComboBox, que como sabrs, con los controles de Visual Studio 2005 es algo que podemos hacer de forma automtica, gracias a las propiedades AutoCompleteMode y AutoCompleteSource. En Las versiones anteriores de Visual Studio debemos hacerlo de forma manual, y en este ejemplo que te pongo aqu, aunque est hecho con Visual Basic 2005 (y con Visual C# 2005, porque, como de costumbre te lo muestro en los dos lenguajes), tambin ser vlido para usarlo con las versiones anteriores, aunque yo no lo he probado, ya que hace unas semanas decid desinstalar el Visual Studio 2003, as que... supongo que se podr hacer de igual forma. De todos modos, en este artculo uso como ejemplo un control DataGridView, que aunque no es "obligatorio" para el ejemplo, si que hace que este cdigo que te muestro solo sea vlido para Visual Studio 2005, pero... con unos pocos cambios puedes convertirlo para las versiones anteriores.
1 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
tendrs que modificar la cadena de conexin y el tipo del "DataAdapter" usado para acceder a los datos. Esa base de datos se llama PruebasGuille y tiene una tabla llamada Clientes. Esa tabla tiene varios campos, pero en este ejemplo solo se usan dos: Nombre y Apellidos. En el formulario de ejemplo uso estos controles: (ver la figura 1)
Figura 1. El formulario en modo de diseo Una etiqueta, una caja de textos llamada txtApellidos, un ListBox para mostrar lo que se vaya encontrando conforme escribes, esa lista se llama listaApellidos. Tambin hay un control de tipo DataGridView en el que se mostrarn los datos que hemos ledo de la base de datos, ese control se llama datosClientes. 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 aplicacin), y se van mostrando los datos en la lista. En la figura 2 puedes ver un ejemplo al escribir la letra M.
2 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
Nota: Junto al texto, te muestro el cdigo 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, tendrs que definir un objeto del tipo DataTable que ser donde estn 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), tendrs 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 tipo SqlDataAdapter. Y como es posible que use otras cosas (que en este caso no las uso), lo mejor es aadir una importacin al espacio de nombres en el que est definido el adaptador:
Imports System.Data Imports System.Data.SqlClient
Tambin necesitas la cadena de conexin 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 conexin Private conexion As String = _ "Data Source = (local)\SQLEXPRESS; " & _ "Initial Catalog=PruebasGuille; " & _ "Integrated Security=true"
La cadena de seleccin (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 seleccin ' los datos que traeremos de la base de datos. Private seleccion As String = _ "SELECT Nombre, Apellidos FROM Clientes"
3 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
End Sub
Fjate en dos detalles del cdigo anterior: 1- Asigno una cadena vaca a la caja de textos. Esto es por si tena algo escrito. 2- 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 cdigo del formulario le asigno un valor falso.
Fjate 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 (adems 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 cdigo Private iniciando As Boolean = True
4 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
Que traducido al lenguaje que entiende el mtodo 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 ms cosas despus 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 "M", se mostrarn todos los que coincidan, que es lo que puedes ver en la figura 2. Pero si en vez de usar el cdigo mostrado antes, usas este otro:
filas = dt.Select("Apellidos LIKE '%" & txtApellidos.Text & "%'")
Como estamos usando los caracteres comodines antes y despus de lo que se escriba, el resultado al escribir la letra "M" ser el que ves en la figura 3, que si te fijas en la lista, hay ms de los 2 datos que mostr el primer cdigo que us para la captura de la figura 2, ya que se encuentran todos los que tenga alguna letra M en los apellidos, adems de que no se hace distincin de si estn en maysculas o minsculas.
5 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
Como los datos se muestran en la lista tienen los apellidos separados del nombre con una coma, vamos a tener en cuenta ese caso, de forma que haremos una bsqueda doble, por el apellido y por el nombre. Dnde buscamos? En cada "celda" de cada fila del control DataGridView (como puedes comprobar algo poco eficiente si tenemos muchsimos datos, pero... eso es lo que hay, je, je). Una cosa que me ha pasado es que si lo que se busca no est... pues no est, vale, pero lo raro es que me daba un error de objeto no inicializado... y ahora que estoy escribiendo esto, estoy pensando que... s, que pasa?, algunas veces pienso despus de hacer las cosas y de tirarme nosecuantas horas intentando resolver el fallo... A lo que iba, ese fallo seguramente sera por la ltima fila del DataGridView est vaca... y como para la bsqueda us un bucle For Each en vez de uno de tipo For con una variable numrica, pues... lo que te muestro, seguro que se puede mejorar, pero... ya sabes... al que no le guste, que lo haga mejor! je, je... (que borde est hoy el Guille). Como te deca, si hay una coma en el texto seleccionado, se toma lo que haya antes como los apellidos y lo que haya despus como el nombre, y se busca en el contenido del DataGridView. Si no hay coma, se busca solo por los apellidos. Fjate tambin que hago una llamada al mtodo ClearSelection del DataGridView para quitar la seleccin anterior que hubiera. Y para asegurarnos de que el elemento seleccionado es visible, asigno el ndice a FirstDisplayedScrollingRowIndex, ese ndice lo obtengo de la fila que coincide con la bsqueda. Aqu tienes el cdigo del evento SelectedIndexChanged del control ListBox, de forma que al pulsar en uno de los elementos de la lista se ejecute este cdigo.
6 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
Private Sub listaApellidos_SelectedIndexChanged( _ ByVal sender As Object, _ ByVal e As EventArgs) _ Handles listaApellidos.SelectedIndexChanged If iniciando Then Exit Sub ' Al hacer clic, mostrar el dato Me.txtApellidos.Text = Me.listaApellidos.SelectedItem.ToString ' Buscarlo en el DataGridView (de forma manual, no conozco otra forma...) ' Eliminar las selecciones anteriores Me.datosClientes.ClearSelection() ' Recorrer las filas para buscar el Apellido indicado For Each fila As DataGridViewRow In Me.datosClientes.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 vaca... If fila.Cells("Apellidos").Value Is Nothing _ OrElse fila.Cells Is Nothing Then Continue For End If ' Si se quiere tener en cuenta el nombre y los apellidos Dim i As Integer = Me.txtApellidos.Text.IndexOf(",") If i > -1 Then ' En este ejemplo, el formato es Apellidos, Nombre Dim nombre, apellidos As String apellidos = Me.txtApellidos.Text.Substring(0, i).TrimEnd() nombre = Me.txtApellidos.Text.Substring(i + 1).TrimStart() If nombre = fila.Cells("Nombre").Value.ToString _ AndAlso apellidos = fila.Cells("Apellidos").Value.ToString Then ' Seleccionamos la fila Me.datosClientes.Rows(fila.Index).Selected = True ' nos aseguramos de que sea visible Me.datosClientes.FirstDisplayedScrollingRowIndex = fila.Index Exit For End If Else If Me.txtApellidos.Text = fila.Cells("Apellidos").Value.ToString Then ' Seleccionamos la fila Me.datosClientes.Rows(fila.Index).Selected = True ' nos aseguramos de que sea visible Me.datosClientes.FirstDisplayedScrollingRowIndex = fila.Index Exit For End If End If Next End Sub
Y esto es todo... espero que te de una idea de cmo hacerlo y que lo sepas adaptar a tus necesidades. Esa es la intencin! Y si te sientes "rumboso", pues acurdate de dejar tu granito de arena en forma de donacin con PayPal. Gracias.
Por cierto, en el ZIP con el cdigo de ejemplo he aadido dos ficheros con la extensin .sql que los puedes usar para crear la tabla y aadir unos cuantos datos de prueba. Para crear la base de datos y usar esos ficheros, puedes usar el Management Studio de SQL Server 2005 Express (o el normal). Y los pasos que debes dar son los que te explico en:
7 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
El cdigo para C#
//----------------------------------------------------------------------------// Ejemplo de buscar datos de una tabla conforme se escribe (13/Abr/07) // // Guillermo 'guille' Som, 2007 //----------------------------------------------------------------------------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 cdigo 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 conexin private string conexion = @"Data Source = (local)\SQLEXPRESS; " + "Initial Catalog=PruebasGuille; " + "Integrated Security=true"; // La cadena de seleccin // 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.txtApellidos.Text = ""; da = new SqlDataAdapter(seleccion, conexion); dt = new DataTable(); da.Fill(dt); this.datosClientes.DataSource = dt; iniciando = false;
8 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
} private void txtApellidos_TextChanged(object sender, EventArgs e) { if (iniciando) return; // Buscar en el DataTable usando el mtodo Select // que es como un filtro WHERE en una cadena de seleccin. // El resultado se devuelve como un array de tipo DataRow DataRow[] filas; // Aqu es donde hay que hacer el filtro de cmo buscar // Usando % ... % no se tiene en cuenta dnde est el apellido escrito // (puede ser el primero o el segundo) // Si escribes "s" se buscarn todos los que contengan esa letra. filas = dt.Select("Apellidos LIKE '%" + txtApellidos.Text + "%'"); // Borrar los elementos anteriores this.listaApellidos.Items.Clear(); // Si hay datos, mostrar los apellidos if (filas.Length > 0) { // Recorrer cada fila y mostrar los apellidos foreach (DataRow dr in filas) { // Tambin puedes mostrar cualquier otro campo, // pero siempre que est en la cadena de seleccin // usada al cargar los datos this.listaApellidos.Items.Add(dr["Apellidos"].ToString() + ", " + dr["Nombre"].ToString()); } } } private void listaApellidos_SelectedIndexChanged(object sender, EventArgs e) { if (iniciando) return; // Al hacer clic, mostrar el dato this.txtApellidos.Text = this.listaApellidos.SelectedItem.ToString(); // Buscarlo en el DataGridView (de forma manual, no conozco otra forma...) // Eliminar las selecciones anteriores this.datosClientes.ClearSelection(); // Recorrer las filas para buscar el Apellido indicado foreach (DataGridViewRow fila in this.datosClientes.Rows) { // Si es el mismo apellido del textBox // // // // if { } // Si se quiere tener en cuenta el nombre y los apellidos int i = this.txtApellidos.Text.IndexOf(","); if (i > -1) { // En este ejemplo, el formato es Apellidos, Nombre string nombre, apellidos; apellidos = this.txtApellidos.Text.Substring(0, i).TrimEnd(); nombre = this.txtApellidos.Text.Substring(i + 1).TrimStart(); if (nombre == fila.Cells["Nombre"].Value.ToString() && apellidos == fila.Cells["Apellidos"].Value.ToString()) { // Seleccionamos la fila this.datosClientes.Rows[fila.Index].Selected = true; // nos aseguramos de que sea visible this.datosClientes.FirstDisplayedScrollingRowIndex = fila.Index; break; } } 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 vaca... (fila.Cells["Apellidos"].Value == null || fila.Cells == null) break;
9 de 10
17/03/2012 15:27
http://www.elguille.info/NET/ADONET/autoCompletar_basedatos.htm
else { if (this.txtApellidos.Text == fila.Cells["Apellidos"].Value.ToString()) { // Seleccionamos la fila this.datosClientes.Rows[fila.Index].Selected = true; // nos aseguramos de que sea visible this.datosClientes.FirstDisplayedScrollingRowIndex = fila.Index; break; } } } } }
Fichero con el cdigo de ejemplo: BuscarMientrasEscribe.zip - 27.5 KB Contiene los proyectos para Visual Basic 2005 y Visual C# 2005, adems de los dos ficheros script para SQL Server 2005 con los que podrs crear la tabla Clientes y aadir algunos datos de prueba. (MD5 checksum: 02FFD04631DA2785CF781E54EA215E53)
10 de 10
17/03/2012 15:27