El objetivo de este ejemplo es demostrar como realizar búsquedas utilizando Linq y una control datagridview
Algo que debe remarcarse es que en el control datagridview se debe permitir la selección múltiple de la celdas, o sea la propiedad
MultiSelect = true
Además se debe especificar la propiedad SelectionMode = CellSelect
La búsqueda tiene dos procesos, el primero determina que las filas cumplen con el filtro especiado, y una ves obtenidas las filas se procede a determinar que celdas especificas aplican al filtro para seleccionarlas.
El objetivo final es demostrar la facilidad que se obtiene con linq para poder realizar búsquedas en el control DataGridView.
List<DataGridViewRow> rows = (from item in dataGridView1.Rows.Cast<DataGridViewRow>() let clave = Convert.ToString(item.Cells["clave"].Value ?? string.Empty) let modelo = Convert.ToString(item.Cells["modelo"].Value ?? string.Empty) let descripcion = Convert.ToString(item.Cells["descripcion"].Value ?? string.Empty) where clave.Contains(busqueda) || modelo.Contains(busqueda) || descripcion.Contains(busqueda) select item).ToList<DataGridViewRow>(); foreach (DataGridViewRow row in rows) { List<DataGridViewCell> cells = (from item in row.Cells.Cast<DataGridViewCell>() let cell = Convert.ToString(item.Value) where cell.Contains(busqueda) select item).ToList<DataGridViewCell>(); foreach (DataGridViewCell item in cells) { item.Selected = true; } }
Como se observa en el ejemplo la primer consulta linq permite determinar que Rows cumplen la condición de búsqueda, para ello se evalúa cada celda de la fila.
Un punto ha remarcar es que el habilitar la propiedad AllowUserToAddRows genera una fila adicional en la grilla que será tratada en la consulta linq como si fuera una adicional, el problema con esta fila es que produce un valor null cuando se intenta utilizar la propiedad Value de la celda. Es por ello que en la consulta se observara el uso del operador ?? el cual ante un null devuelve una cadena vacía.
Igualmente el punto anterior podrías haberse evitado el uso de ?? ya que al convertir a string con Convert.ToString() evita el problema con el null.
Si la idea era seleccionar las filas que cumplan la condición con el primera consulta linq ya era suficiente, pero si se quiere ir especialmente a las celdas, es necesario dar un paso mas.
Es por ello que la segunda consulta trabaja a nivel de las celdas, tomando cada fila que cumple con la condición y determinado que celdas especifica también lo hace, para luego marcarla como seleccionada.
[C#]
|
[VB.NET]
|
Hola,
ResponderEliminar¿por qué haces dataGridView1.Rows.Cast()?, es para que item se carge con una colección IEnumerable de DataGridViewRow.
¿Por que item no se puede cargar directamente con la colección de DataGridRow de Rows?.
Muchas gracias y un saludo.
hola sr leandro tuttini , no se si me puede ayudar tengo un problemita estoy haciendo un formulario donde cargo un archivo de texto en un datagridview esa informacion la quiero almacenar en una base de datos como le hago???
ResponderEliminarhola ATP, disculpa la demora en contesta, es que no habia recibido alerta de tu pregunta.
ResponderEliminar¿por qué haces dataGridView1.Rows.Cast()?
El Cast() permite adaptar la coleccion de filas de la grilla para poder ser consultada por Linq.
Recuerda que Linq necesitas de ciertas interfaces o tipo de objetos para que sea posible aplicar la consulta, no todas las listas se pueden consultar con linq, con el DataSet sucede lo mismo hay que adaptar estas colecciones para poder ser trabjadas en Linq.
¿Por que item no se puede cargar directamente con la colección de DataGridRow de Rows?
No se puede cargar directamente porque las colecciones o listas que se usan son diferentes.
El DataGridView esta usando un DataGridViewRowCollection, mientras que la query en Linq no puede usar este tipo de datos, por defecto sino se usa el ToList<>(), estaria devolviendo un
IEnumerable
Hay que iterar por cada registro para trabajarlo.
saludos
hola julio
ResponderEliminarDos puntos importantes que no has mencionado es que lenguaje usar para programar y que base de datos piensas usar.
por lo pronto puedo mostrarte un ejmeplo en C# y Sql Server:
using (SqlConnection conn = new SqlConnection(""))
{
conn.Open();
string query = @"INSERT INTO Tabla (descripcion, stock, precio)
VALUES (@desc, @stock, @precio)";
SqlCommand cmd = new SqlCommand(query, conn);
foreach(DataGridViewRow row in dataGridView1.Rows)
{
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("@desc", Convert.ToString(row.Cells["Descripcion"].Value));
cmd.Parameters.AddWithValue("@stock", Convert.ToInt32(row.Cells["Stock_ID"].Value));
cmd.Parameters.AddWithValue("@precio", Convert.ToDecimal(row.Cells["Precio"].Value));
cmd.ExecuteNonQuery();
}
}
Como veras se recorrer cada uno de las filas, y en cada vuelta se tomas los datos de las celdas para pasarselas al parametro de la query
saludos
Hola.
ResponderEliminarEstoy tratando de hacer el ejemplo pero la colección Rows no tiene el miembro Cast.
Cambié el destino del proyecto (a Framework 3.5), agregué a mano las referencias a Linq dentro del proyecto y dentro del código pero no me sale igualmente.
Tenés idea lo que puede ser?
Gracias.
hola Diego
ResponderEliminarRealiza una prueba, crea un proyecto nuevo que use .net 3.5
Luego intenta armar un ejemplo simple de linq que use una grilla hje intenta acceder a ese metodo que no puedes utilizar, valida que alli puedas.
Si puedes entonces claramente el otro proyecto al cambia de version de framework algo falto.
Pero primero descartemos que puedes acceder a este metodo desde un proyecto creado con .net 3.5 desde su comienzo.
saludos
Este comentario ha sido eliminado por el autor.
ResponderEliminarHola Leandro, tengo algunas dudas, si realizado la busqueda desde un formulario dependiente del formulario donde se encuentra la grilla no me muestra la celda encontrada, mi codigo en el formulario dependiente es el siguiente:
ResponderEliminar//Determinar que filas cumplen un filtro determinado
List rows = (from item in ((PantallaConsulta)this.Owner).dgvBuscar.Rows.Cast()
let nom_mod = Convert.ToString(item.Cells["Nom_Mod"].Value ?? string.Empty)
let descripcion_moda = Convert.ToString(item.Cells["Descripcion_Moda"].Value ?? string.Empty)
let descripcion_segm = Convert.ToString(item.Cells["Descripcion_Segm"].Value ?? string.Empty)
where nom_mod.Contains(busqueda) ||
descripcion_moda.Contains(busqueda) ||
descripcion_segm.Contains(busqueda)
select item).ToList();
//MessageBox.Show(rows.ToString());
//Obtenidas las filas se procede a determinar que celdas especificas aplican al filtro para seleccionarlas
foreach (DataGridViewRow row in rows)
{
List cells = (from item in row.Cells.Cast()
let cell = Convert.ToString(item.Value)
where cell.Contains(busqueda)
select item).ToList();
foreach (DataGridViewCell item in cells)
{
item.Selected = true;
}
}
¿Que cambio habria que realizar para que me seleccione la fila en vez de la celda?
Para que el texto escrito no tenga que coincidir completamente, que sea una subcadena del contenido de la celda ¿tiene solucion?
Son muchas preguntas, lo siento, responde si puedes y muchas gracias por tu tiempo.
Hola Leandro
ResponderEliminarPrimero que nada darte las gracias por la ayuda inestimable.
La pregunta es, se puede utilizar linq con visual basic 2008?, lo digo por que yo no estoy muy puesto en el c#, ni tampoco en linq, pero me gustaría aprender como va.
Gracias por adelantado.
Jota69
hola elChele
ResponderEliminarclaro se puede usar Linq con VS.NET, pero recuerda crear el proyecto usando .net 3.5
Introducción a LINQ en Visual Basic
saludos
HOLA LEANDRO PORFAVOR AYUDAME,
ResponderEliminarTENGO UN SISTEMA PARA UNA TIENDA DE VIDEOJUEGO TENGO UNA DATAGRID DONDE CARGUE MI BASE DE DATOS, YA PUEDO GUARDAR MAS DATOS PERO NO SE ELIMINARLOS, POR FAVOR AYUDAME A ELIMINAR UNA FILA DE DATOS CON ALGUN CODIGO EN C# PARA VISUAL STUDIO 2010
hola de diseño
ResponderEliminarbien para eliminar un registro podrias usar
private void btnEliminar_Click()
{
DataGridViewRow row = DataGridView1.CurrentRow;
if(row == null)
{
MessageGox.Show("debe seelccionar una fila para eliminar");
return;
}
using (SqlConnection conn = new SqlConnection("connection string")
{
string sql = @"DELETE FROM NombreTabla WHERE campo = @param";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@param", Convert.ToInt32(row.Cells["colnombre"].Value));
cmd.ExecuteNonQuery();
}
}
por supuesto como no indicaste que en que lenguaje programaste puse el ejemplo en c#
pero peude convertirlo usando
convert tool
saludos
excelente papa
ResponderEliminartengo una datagrid con muchos registros, la consulta al datagrid me funciona perfectamente, pero tengo un problema: si el registro selecionado esta al final de datagridview me toca desplazarme hasta abajo o hasta encontrarlo, como hago para que me lo muestre en pantalla sin necesidad de desplazarme. gracias
ResponderEliminarhola dubier
ResponderEliminarno has intentado usar la propiedad
FirstDisplayedScrollingRowIndex
si le pones el index de la fila seleccionada desplazara el grid a ese lugar
saludos
Leandro, me podrias indicar como capturo el index? gracias. o cual es la variable DataGridView1.FirstDisplayedScrollingRowIndex = ??
ResponderEliminarhola dubier
ResponderEliminarcuando trabajas con el DataGridViewRow obtienes el index de esa row en concreto del datagridview
imagino a ese DataGridViewRow lo seleccionas con Selected= true, bueno ademas de eso extraes el index y lo asignas a la propiedad.
DataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
saludos
hola leandro, estoy buscando un dato en la columna [producto] y este me busca perfectamente en esa columna. solo en esa, pero al hacer foreach para selecionar los item, estos me selecionan las demas columnas donde cioncidan las palabras de busqueda. me podrias ayudar? ya que solo quiero que se me selecionen solo en [producto]. gracias
ResponderEliminarhola dubier
ResponderEliminarun efecto algo extraño el que comentas
Como es que estas aplicando el filtro?
y como es que recorres los items
quizas sea dificil poner aqui el codigo, podrias plantear la consulta en el foro y la seguimos alli
foro msdn
saludos
como puedo lograr la búsqueda, sin que afecte como esté escrito al registro: "Silla", "silla", "SILLA". Gracias de antemano
ResponderEliminarhola jesusM
ResponderEliminarpara comparar usas el Contains() ?
porque podrias hacer:
campos.ToLower().Contains(texto.ToLower())
o sea llevas todo a minusculas y comparas, asi ya no afectara
saludos
Que tal, creo que no me di a entender, sí uso el Contains, pero en las rejillas de mi DataG al estár relacionada con mi bd no siempre tienen un formato definido, y pues el detalle es que para la búsqueda, usando el parámetro de la caja de texto no coincide con lo que tengo en el Grid, como es llenado por varias persona, a veces escriben silla o SILLA como te explique anteriormente, como puedo solucionar ese dilema?
ResponderEliminarhola jesusM
ResponderEliminarpero estas realizando una busqueda con linq ?
porque si es asi al llevarlo a minuscula a ambos texto a minuscula ambos texto coinciden y el Contains dira que son iguales
sino la otra es usa IndexOf()
String.IndexOf Method (String, StringComparison)
o sea en el link usarias en el where
item.IndexOf(txtBuscar.Text, StringComparison.InvariantCultureIgnoreCase) > 0
o sea buscarias si devuelve uan posocion, si lo hace es porque lo contiene
saludos
hola como va, leandro como puedo hacer para mostrar en un datagridview los datos de tres tablas todo esto con linq to sql la verdad que e estado lidiando por mucho y no logro hacerlo desde ya muchas gracias por tus aportes.
ResponderEliminarhola luis
ResponderEliminarpodrias crear una entidad auziliar con las propiedades que quieras visualizar en el grid, estas propiedades seria de varias de las entidades
public class EntidadAux{
public string ProdId {get;set;}
public string ProdDesc {get;set;}
public string CatId {get;set;}
public string CatDesc {get;set;}
}
entonces con linq lo que ahces en el select es devolver una lista de EntidadAux, asignando la info tomada de un poco de cada entidad que relacionaste mediante un join
saludos
hola leandro ya te había comentado este problema pero te lo vuelvo a explicar, he descargado el ejemplo tuyo en c#, y quiero buscar en el ejemplo tuyo la palabra LI esa palabra esta en Modelo y Descripción. ósea está LI10V OS y LICUADORA DE 10 VEL. OSTER ahora le quito las siguientes líneas solo para que me busque ese dato solo en la columna modelo.
ResponderEliminarlet descripcion = Convert.ToString(item.Cells["descripcion"].Value ?? string.Empty)
|| descripcion.Contains(busqueda)
Con esto solo me debería buscar en la columna modelo, pero no todavía me resalta las dos filas. Gracias por la ayuda.
hola dubier
ResponderEliminarpero cuando cometas que tienes LI10V OS y LICUADORA DE 10 VEL. OSTER
en que columna estan estos dos textos que mencionas ? no estaran en la columna descripcion, no ?
saludos
hola Leandro te ago una pregunta
ResponderEliminarcomo se, o de donde saco el valor de
SelectedCells[] tengo esto.
txtCuit.Text = selCli.dtgClientes.SelectedCells[4].Value.ToString();
txtCliente.Text = selCli.dtgClientes.SelectedCells[1].Value.ToString();
no se de donde tomo el valor cual es la referencia se que se lo asigno al txtbox desde el datagrid pero como se a a que valor corresponde. desde ya muchas gracias
hola luis
ResponderEliminarel SelectedCells deberis usarlo desde un evento CellClick o CellDoubleClick, del datagridview
en el contexto de estos eventos podras saber cual es la delda seleccionada
si lo haces desde otros eventos imaginemos un click de un boton, debes tener cuidado porque esa propiedad podria venir en null sino hay nada seleccionado
saludos
Leandro un saludo, decir q tus ejemplos me han ayudado mucho, te planteo mi inconveniente, yo cargo mi datagrid con un archivo de excel de al menos unos dos mil registros en 3 columnas, con tu codigo me realiza la busqueda .. pero digamos en el datagridview se muestran registros hasta el número 20 y para ver el resto uso el scroll o la barra lateral izq, digamos doy a buscar el registro en la fila numero 300 y me lo encuentra pero no me desplaza el datagridview hasta alla tengo q usar la barra lateral izq. ¿como haría para que me desplace a la celda cuando encuentra el dato?
ResponderEliminarhola Nelson
ResponderEliminarpodrias usar el
FirstDisplayedScrollingRowIndex
asignando el index de la row que has encontrado desplaza directo el scroll a esa posicion
saludos
Leandro gracias por tus aportes son de mucha ayuda.
ResponderEliminarcomo adapto este código para que solo me muestre en el datagridview los registro que coinciden con la búsqueda.
Gracias
hola Israel
ResponderEliminarpodrias aplicar linq no sobre el datagridview directamente sino sobre los datos de este tiene asignado
si usas un datatable el linq lo puedes aplicar sobre este para filtrar los datos y luego asignarlos al grid
saludos
Buenas noches, Se puede ingresar en un DataGridView --> "Persona.tipoPersona.Descripcion" no se la forma de hacerlo porfavor si podria ayudarme. Si pude con Persona.nombre Persona.direccion .....
ResponderEliminarhola Javier
ResponderEliminaraqui respondo sobre el mismo planteo
Acceder a Objeto Anidado desde una DataGridView
saludos
Hola Leandro !!!
ResponderEliminarBuen día ... Apliqué el ejemplo para filtrar filas en el datagridview... Yo quisiera que al filtrar, las filas que no coinciden no se vean... Es posible hacerlo sin usar datatable? O sea con los datos que estan cargados en el datagrid?
Salu2! y gracias por tus aportes que nos salvan dia a dia. :)
hola Migue
ResponderEliminarno veo como podrias filtrar directo en el grid sin tener una lista
podrias usar un datatable o crear una lista generica con uan clase que tu definas
de esta forma aplcias linq de forms simple y luego el resultado lo muestras en el grid
pero podrias tener en una variable la lista original asi no perder los datos y filtrar siempre sobre estos
saludos
Sos un groso... No hay más palabras para definirte... Yo no sé como Bill no te lleva a laburar al Norte...
ResponderEliminarSalu2! genio...
Hola Leandro, esto es justo lo que necesitaba, muchas gracias funciona a la perfección, solo un pequeño detalle. ¿Hay alguna función para hacer que si la grilla es demasiado grande desplace la vista hacia el ítem seleccionado? Muchas Gracias !
ResponderEliminarEstimados, necesito una sentencia de LINQ para una aplicación en VB.Net.
ResponderEliminarAgradezco mucho si alguien me puede ayudar.
Tengo las siguientes clases
Clase AcumuladosRegion
CodSuc
TotalVenta
Clase Empresa
CodEmp
Nombre
Pais
Acumulados de tipo collection (colección de la clase AcumuladosRegion )
En un formulario tengo una Lista de Empresas LisEmpresas de tipo List (of Empresa)
A modo de ejemplo, los datos son
CodEmp Pais Nombre Acumulados
1 ARG Empresa1 RegionNorte=35 RegionSur=20 RegionEste=45 RegionOeste=15
2 ARG Empresa2 RegionNorte=10 RegionSur=10 RegionEste=65 RegionOeste=10
3 PERU Empresa3 RegionNorte=15 RegionSur=20 RegionEste=20 RegionOeste=10
4 PERU Empresa4 RegionNorte=10 RegionSur=25 RegionEste=30 RegionOeste=30
5 PERU Empresa5 RegionNorte=15 RegionSur=10 RegionEste=30 RegionOeste=10
Mediante LinQ necesito obtener el siguiente resultado
Pais TotalPorRegion
ARG RegionNorte=45
ARG RegionSur=30
ARG RegionEste=110
ARG RegionOeste=25
PERU RegionNorte=40
PERU RegionSur=55
PERU RegionEste=80
PERU RegionOeste=50
Es decir, una SENTENCIA LINQ que tome de LisEmpresas, agrupe por país y genere total de cada región
hola Horacio
ResponderEliminardemasiado grande con respecto al form ?
no entendi lo de la vista y el item
saludos
hola Andres
ResponderEliminarpodrias usar el grouo by de linq
algo como ser
Dim result = From emp In LisEmpresas
Group By Key = emp.Pais Into Group
Select New With {
.Pais = Key,
.RegionNorte = Group.Sum(Function(x) x.RegionNorte),
.RegionSur = Group.Sum(Function(x) x.RegionSur),
.RegionEste = Group.Sum(Function(x) x. RegionEste),
.RegionOeste = Group.Sum(Function(x) x. RegionOeste),
}
Group By Clause (Visual Basic)
saludos
hola leandro intente descargar los ejemplos completos y los anlaces estan caidos, sera que puedes resubirlos :) gracias de antemano
ResponderEliminarhola Leandro!! te queria comentar que probe el codigo que subiste para filtrar datos de un datagridview pero me marca un error. En el datagriview me sale lo siguiente
ResponderEliminarcontextMenuStr DefaultCellStyle DividerHeigth ErrorText Heigth ReadOnly osea todas esas columnas y otras mas en blanco