Hace unos dias que lo estoy probando pero no hay manera. Resulta que tengo tengo un
datagridview, donde le asigno como datasource un dataset con datos, y luego le asigno el
datamember, y me muestra los datos. Hasta aqu ningun problema. El problema viene cuando
quiero vaciar este datagridview porque simplemente no quiero mostrar ninguna informacin en
l, vamos, que lo quiero vaciar. He probado asignandole el datasource a null, pero visualmente el
datagridview sigue con datos. Tambien he probado con la funcion Clear() pero tampoco. Que
hago mal?
Otra forma de vaciarlo, al menos en c# es:
DataGridView1.Rows.Clear();
Luego :
private void frmCliente_Load(object sender, EventArgs e)
{
dgvPersona.DataSource = Persona.CargarGrilla();
FormartoGrilla();
}
Pedro vila
"El hombre sabio querr estar siempre con quien sea mejor que l."
Lima - Per
}
void dText_KeyPress(object sender, KeyPressEventArgs e)
{
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
{
e.KeyChar = char.ToUpper(e.KeyChar);
}
}
[VB.NET]
[C#]
[VB.NET]
}
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
{
dText.KeyPress -= new KeyPressEventHandler(dText_KeyPress);
}
[C#]
[VB.NET]
C# - [DataGridView]
DataGridViewComboBoxColumn Variar contenido
del combobox respecto a la fila
Introduccin
El objetivo del articulo es demostrar algunos problemas que pueden surgir cuando se necesita que
el ComboBox ubicado en las celdas del DataGridView, vare su contenido de acuerdo al registro
que se visualiza.
Para demostrar el problema, se ha definido un dominio del ejemplo intentara cargar una grilla de
sucursales, de los cuales mostraran el listado de los telfonos disponibles.
Por supuesto para cada sucursal los telfonos disponibles varan, por lo tanto definir el contenido
del combo como una nica lista no es posible.
Carga del contenido variable en ComboBox
En el evento Load del formulario se procede a la carga de las sucursales, e inmediatamente
despus de esta operacin se invoca a un mtodo creado con el fin de la carga de los combos de
cada registro de a grilla.
Este mtodo recorre en un ciclo cada registro, toma el id de la sucursal que se encuentra en la
celda del registro actual, y tambin toma la celda que representa el combo.
Con las anteriores dos selecciones procede a realizar una consulta a los datos y cargar en el
combo los telfonos de esa sucursal.
[C#]
[VB.NET]
Para esta operacin se requerir la ayuda del DataSet tipado el cual define la estructura de la
entidad, pero ser responsabilidad de la clase con sufijo DAL, la que cargara la informacin,
proveniente de la base de datos.
private void frmPedidos_Load(object sender, EventArgs e)
{
//
// Se recupera los datos de los productos desde la tabla
//
dtoProductos datos = ProductoDAL.ProductosGetAll();
//
// Se bindean los datos a la grilla
//
dgvProductos.AutoGenerateColumns = false;
dgvProductos.DataSource = datos;
dgvProductos.DataMember = "Productos";
}
Seleccin de un tem en la grilla de origen
Hay que destacar que la operacin sobre un DataGridView difiere si esta se encuentra previamente
enlazada a datos, o no.
En esta primera operacin implica la seccin de un producto que pasara a una lista no enlazada a
datos, por lo tanto se podr hacer uso de mtodo Add() de la coleccin de Rows de la grilla.
private void btnSeleccionar_Click(object sender, EventArgs e)
{
//
// Se define una lista temporal de registro seleccionados
//
List<DataGridViewRow> rowSelected = new List<DataGridViewRow>();
//
// Se recorre ca registro de la grilla de origen
//
foreach (DataGridViewRow row in dgvProductos.Rows)
{
//
// Se recupera el campo que representa el checkbox, y se valida
la seleccion
// agregandola a la lista temporal
//
DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"] as
DataGridViewCheckBoxCell;
if (Convert.ToBoolean(cellSelecion.Value))
{
rowSelected.Add(row);
}
//
// Se agrega el item seleccionado a la grilla de destino
// eliminando la fila de la grilla original
//
foreach (DataGridViewRow row in rowSelected)
{
dgvSeleccion.Rows.Add(new object[] {false,
row.Cells["Descripcion"].Value,
row.Cells["PrecioUnitario"].Value,
row.Cells["UnidadMedida"].Value});
dgvProductos.Rows.Remove(row);
}
}
Hay que remarcar tambin que el uso de la lista temporal no es un capricho, sino que es necesaria
ya que mientras se recorre una lista por medio de la instruccin for each, no pueden removerse
elementos. Por esta razn es que en una operacin siguiente se recorre la seleccin y all si se
procede a incluye los tems en al grilla de destino y quitarla de la original.
Ahora le toca el turno a la operacin contraria, y aqu hay un punto que ya se menciono en el paso
previo, la lista de origen esta vinculada a datos de productos con lo cual usar el Rows.Add() no es
posible.
Para esta operacin se agregaran los datos directo en el origen, en este caso el datatable, que se
ha creado dentro del DataSet tipado.
private void btnQuitar_Click(object sender, EventArgs e)
{
//
// Se define una lista temporal de registro seleccionados
//
List<DataGridViewRow> rowSelected = new List<DataGridViewRow>();
//
// Se recorre cada fila de la grilla de seleccion y se determian que
registros estan checkeados
//
foreach (DataGridViewRow row in dgvSeleccion.Rows)
{
DataGridViewCheckBoxCell cellSelecion = row.Cells["SeleccionSel"]
as DataGridViewCheckBoxCell;
if (Convert.ToBoolean(cellSelecion.Value))
{
rowSelected.Add(row);
}
}
//
// Se valida si hay algun registro por eliminar
//
if (rowSelected.Count > 0)
{
//
// Se recupera el origen de datos que tiene asignada la grilla de
productos
//
dtoProductos datos = dgvProductos.DataSource as dtoProductos;
//
// Se recorre cada item seleccionado y se arma programaticamente
la fila del DataTable
// se elimina el registro de la grilla de selecciones
//
[C#]
[VB.NET]
Para realizar la tarea se har uso de dos eventos que pueden ser igual de tiles, el
CellValueChange y el CellContentClick
De forma estndar el CellValueChange, se deparar a seleccionar el check de la celda y quitar el
foco de la misma, saliendo del modo de edicin.
Pero este no ejecuta la accin en el mismo instante en que se origina, sino que hay que salir de la
edicin de la celda para que el evento ocurra.
private void dataGridView1_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
//
// Solo se trabaja ante los cambios en la columan de los checkbox
//
if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion") {
//
// Se toma la fila seleccionada
//
DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
//
// Se selecciona la celda del checkbox
//
DataGridViewCheckBoxCell cellSelecion =
row.Cells["Seleccion"] as DataGridViewCheckBoxCell;
//
// Se valida si esta checkeada
//
if (Convert.ToBoolean(cellSelecion.Value)) {
string mensaje = string.Format("Evento
CellValueChanged.\n\nSe ha seccionado, \nDescripcion: '{0}', \nPrecio
Unitario: '{1}', \nMedida: '{2}'",
row.Cells["Descripcion"].Value,
row.Cells["PrecioUnitario"].Value,
row.Cells["UnidadMedida"].Value);
MessageBox.Show(mensaje, "", MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
}
Con respecto al CellContentClick, que si ejecuta la accin en el mismo momento en que el usuario
marca, o desmarca, el checkbox, pero me encontr que solo devolva null en la propiedad Value de
la celda.
}
}
Tambin se ha intentado hacer uso del evento EditingControlShowing, el cual permitira detectar la
seleccin en el mismo momento que el usuario realiza la accin, pero esto no fue posible ya que
este tipo de columna no provoca el evento necesario para tomar el control CheckBox y asignar el
evento SelectedIndexChanged.
Ante este problema con los eventos, y notar que ninguno responde como debera, se encontr un
mtodo que resolvi todos los problemas de un solo golpe, se trata del CommitEdit
private void dataGridView1_CurrentCellDirtyStateChanged(object sender,
EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
En el evento CurrentCellDirtyStateChanged, se detecta si la grilla esta con algn cambio pendiente,
y en caso de estarlo se hace un Commit del mismo para reflejar el valor en los eventos que lo
usaran. Esto arregla los dos problemas detectados anteriormente:
- se lanza el evento CellValueChanged, sin tener que quitar el foco de la celda
- ya no se recibe el null en el Value de la celda, en el evento CellContentClick
[C#]
[VB.NET]
[C#]
[VB.NET]
return true;
}
[VB.NET]
Protected Overloads Overrides Function ProcessCmdKey(ByRef msg As
System.Windows.Forms.Message, keyData As System.Windows.Forms.Keys) As
Boolean
'
' Si el control DataGridView no tiene el foco,
' se abandonamos el procedimiento, llamando al metodo base
'
If (Not dataGridView1.Focused) Then
Return MyBase.ProcessCmdKey(msg, keyData)
End If
'
' Si la tecla presionada es distinta al ENTER,
' se abandonamos el procedimiento, llamando al metodo base
'
If keyData <> Keys.Enter Then
Return MyBase.ProcessCmdKey(msg, keyData)
End If
'
' Obtenemos la fila actual
'
Dim row As DataGridViewRow = dataGridView1.CurrentRow
If rbMostrarMensaje.Checked Then
MessageBox.Show(String.Format("Se ha seleccionado,
Cuenta:'{0}' Descripcion:'{1}'", row.Cells("cuenta").Value,
row.Cells("descripcion").Value))
ElseIf rbMostrarForm.Checked Then
Dim cuenta As Integer = CInt(row.Cells("cuenta").Value)
Dim desc As String = CStr(row.Cells("descripcion").Value)
Dim frm As New frmSeleccion(cuenta, desc)
frm.ShowDialog()
End If
Return True
End Function
- El primer punto es detectar si al presionar la tecla el foco lo tiene el control que se quiere trabajar,
en este caso el DataGridView
- El segundo paso es determinar si la tecla presionada por el usuario es la que se desea controlar,
en este caso ser el ENTER
Si las dos validaciones anteriores pasaron, se puede recuperar la fila seleccionada en la grilla, y
trabajar con la informacin que esta proporcione.
[C#]
[VB.NET]
[C#]
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message
msg, System.Windows.Forms.Keys keyData)
{
//
// Si el control DataGridView no tiene el foco,
// se abandonamos el procedimiento, llamando al metodo base
//
if ((!listView1.Focused))
return base.ProcessCmdKey(ref msg, keyData);
//
// Si la tecla presionada es distinta al ENTER,
// se abandonamos el procedimiento, llamando al metodo base
//
if (keyData != Keys.Enter)
return base.ProcessCmdKey(ref msg, keyData);
//
// Sino hay item seleccinado en la lista
// se abandonamos el procedimiento, llamando al metodo base
//
if(listView1.SelectedItems.Count == 0)
return base.ProcessCmdKey(ref msg, keyData);
//
// Obtenemos la fila actual
//
ListViewItem item = listView1.SelectedItems[0];
if (rbMostrarMensaje.Checked)
{
MessageBox.Show(string.Format("Se ha seleccionado, Cuenta:'{0}'
Descripcion:'{1}'",
item.Text,
item.SubItems[1].Text));
}
else if (rbMostrarForm.Checked)
{
int cuenta = Convert.ToInt32(item.Text);
string desc = Convert.ToString(item.SubItems[1].Text);
frmSeleccion frm = new frmSeleccion(cuenta, desc);
frm.ShowDialog();
}
return true;
}
[VB.NET]
Protected Overloads Overrides Function ProcessCmdKey(ByRef msg As
System.Windows.Forms.Message, keyData As System.Windows.Forms.Keys) As
Boolean
'
' Si el control DataGridView no tiene el foco,
[C#]
[VB.NET]
Uno de los problemas al trabajar con el DataGridView y los combos en las celdas, es que no hay
un eventos preciso que sea lanzado al cambiar la seleccin por parte del usuario.
El evento CellValueChanged se podra decir que es el mas cercano a utilizar, pero este solo se
produce cuando la celda se deja de editar, o sea hay que salir de la edicin de la celda, y adems
haber cambiado el tem seleccionado para que el evento se produzca.
Es por este punto que este articulo explicara como adjuntar el combo definido en una columna de
tipo DataGridViewComboBoxColumn, al evento SelectedIndexChanged, el cual de forma estndar
no esta disponible en la grilla.
Se dispone de una grilla, la cual presenta un combo en una de sus columnas, y un check que
habilita la seleccin de la lista de productos.
El usuario al cambiar la seleccin del combo, de forma automtica el sistema debera marcarse el
checkbox en la misma fila en edicin.
[C#]
[VB.NET]
Si bien el ejemplo anterior funciona correctamente a primera vista, hay un efecto que se puede
llegar a manifestarse, el cual no es nada deseable.
Resulta que en ciertas ocasiones luego de haber editado una de las celdas del combo y
seleccionado un tem, esta funciono correctamente y marco el check de la fila.
Pero al editar otra celda en una fila distinta, sin haber cambiado opcin alguna, se dispara el
evento del combo, marcando el check, cuando no debera hacerlo en ese momento, ya que no
hubo cambio de seleccin alguna.
Esto se debe a que el combo queda con el evento asignado, y lo lanza cuando entra en edicin.
Este escenario, si bien resuelve el efecto en la seleccin descripto en los pasos previo, tiene un
punto no tan bonito en el cdigo, ya que debe conservar el control que se esta editando de forma
global al formulario.
Bsicamente la resolucin del problema es realizada mediante la quita del evento del combo
cuando se deja de editar la celda, para lo cual se agrega el evento CellEndEdit.
DataGridViewComboBoxEditingControl dgvCombo;
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
dgvCombo = e.Control as DataGridViewComboBoxEditingControl;
if (dgvCombo != null)
{
dgvCombo.SelectedIndexChanged += new
EventHandler(dvgCombo_SelectedIndexChanged);
}
}
private void dvgCombo_SelectedIndexChanged(object sender, EventArgs e)
{
//
// se recupera el valor del combo
// a modo de ejemplo se escribe en consola el valor seleccionado
//
ComboBox combo = sender as ComboBox;
Console.WriteLine(combo.SelectedValue);
//
[C#]
[VB.NET]
Muchas de las veces que se opera con el control DataGridView es necesario realizar clculos
sobre el mismo, por lo general estos requieres del input del usuario de ciertos valores que
trabajaran sobre otros ya cargados en el control
En este articulo tratare de de mostrar como hacer uso del control DataGridView para poder realizar
estos clculos, reflejando el resultado como totales de filas y columnas.
Esta ser la primer operacin ha realizar, la carga de los datos de los productos en la grilla.
private void frmPedidos_Load(object sender, EventArgs e)
{
//
// Se recupera los datos de los productos desde la tabla
//
dtoProductos datos = ProductoDAL.ProductosGetAll();
//
// Se agrega un registro adicional al DataTable, para representar la
fila de totales
//
dtoProductos.ProductosRow rowTotal =
datos.Productos.NewProductosRow();
datos.Productos.Rows.Add(rowTotal);
//
// Se bindean los datos a la grilla
//
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = datos;
dataGridView1.DataMember = "Productos";
1];
//
// Se selecciona la ultima fila de Totales y se marca como readonly
// para evitar la seleccion por el usuario
//
DataGridViewRow row = dataGridView1.Rows[dataGridView1.Rows.Count row.ReadOnly = true;
//
// Se asigna el evento para detectar los cambios que el usuario
realice
//
dataGridView1.CellValueChanged +=new
DataGridViewCellEventHandler(dataGridView1_CellValueChanged);
}
Como se puede apreciar se realizan algunas operaciones programticamente sobre los datos
antes de bindearlos, por ejemplo una de las principales es al agregado de una fila adicional al final
del datatable ,esta operacin es importante ya que permitir visualizar la fila de totales al final de la
grilla.
Otra operacin importante es realizada luego de bindear, en donde se pone en readonly la ultima
fila para evitar que el usuario la edite.
Algo a remarcar es la asignacin del evento manuablemente en la ultima lnea del evento Load del
formulario, esta asignacin es realizada en este punto ya que si se realiza por medio del cuadro de
propiedades del Visual Studio, el evento CellValueChanged ser lanzado varias veces cuando se
carga la grilla, lo cual se evita al no asignar el el evento al comienzo, este evento solo es necesario
ante la edicin del usuario y no en la carga del mismo.
Calculo de totales
Ante la edicin del campo de pedido o la seleccin de uno de los check de la columna de
seleccin, es que se disparara este evento.
//
foreach (DataGridViewRow row in dataGridView1.Rows)
{
//
// Se selecciona la celda del checkbox
//
DataGridViewCheckBoxCell cellSelecion =
row.Cells["Seleccion"] as DataGridViewCheckBoxCell;
de pedido
//
// Se valida si esta checkeada
//
if (Convert.ToBoolean(cellSelecion.Value))
{
//
// Se valida si el usuario ingreso un valor en la celda
//
decimal pedido = 0;
if (!
decimal.TryParse(Convert.ToString(row.Cells["Pedido"].Value), out
pedido))
continue;
//
// Se realiza el calculo para la fila, asignado el total
en la celda "Total"
// de la misma
//
decimal totalFila =
Convert.ToDecimal(row.Cells["PrecioUnitario"].Value) * pedido;
row.Cells["Total"].Value = totalFila;
//
// Se aumula el total de cada una de las filas
//
totalColumna += totalFila;
}
//
// Se toma la ultima fila del total general, asignando el valor
acumulado en el calculo
//
DataGridViewRow rowTotal =
dataGridView1.Rows[dataGridView1.Rows.Count - 1];
rowTotal.Cells["Total"].Value = totalColumna;
}
}
En este evento se recorrer cada una de las filas de la grilla realizando los clculos a nivel de la
propia fila, pero tambin de la columna de totales.
Adicionalmente se agrego el evento de validacin, ante una entrada incorrecta del usuario en la
celda de pedidos, si el usuario ingresa letras se mostrara un alerta en la fila.
private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Pedido")
{
//
// Si el campo esta vacio no lo marco como error
//
if (string.IsNullOrEmpty(e.FormattedValue.ToString()))
return;
}
}
//
// Solo se valida ante el ingreso de un valor en el campo
//
decimal pedido = 0;
if (!decimal.TryParse(e.FormattedValue.ToString(), out pedido))
{
DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
row.ErrorText = "Debe ingresar un nmero valido";
e.Cancel = true;
}
//
// Este evento es usado al presiona ESC cancelando la edicion
// se elimine el mensaje de error en la fila
//
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
}
Nota: Hay un problema en las validaciones en la grilla. Si por alguna razn cuando usa las
validaciones en el DataGridView, no visualiza el icono con el mensaje del error esto se puede
deber a que la propiedad AutoSizeRowsMode no esta asignada con el valor None.
DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
tenga en cuanta este punto cuando use las validaciones
[C#]
[VB.NET]
Este articulo tendr por objetivo mostrar como trabajar con las columna del tipo ComboBox que se
encuentran dentro de una celda del datagridview.
Un paso importante es la definicin de las columnas para ello en este caso explicare como hacerlo
en tiempo de diseo y poder as controlar que datos visualizar.
La opcin para realizar esta operacin se encuentra haciendo click con el botn derecho del mouse
en el control DataGridView del formulario, visualizando una lista de tems como se muestran en la
imagen
Como se observa en la imagen, puede definirse informacin rpida del tipo de columna que se
quiere representar en la grilla.
- Editar columnas existentes, mediante la opcin Edit Columns visualizando un cuadro como el
siguiente
Lo interesante de esto es que uno podr controlar que visualizar, en que orden, formato, tipo de
columna y adems todo desde un entorno visual
La idea de estos dilogos es definir rpidamente las columnas mediante la opcin de Add
Column para luego pasar a la edicin mediante Edit Columns y especificar propiedades que
son importantes para que todo funcione.
Una de las propiedades importantes es DataPropertyName, esta es fundamental para indicar que
campo del origen de datos ser asignado a esa columna. Al momento de cargar la grilla el valor de
esa propiedad ser tomado del origen de datos y asea un DataTable, o List<>, o cualquier otro que
sea asignado y se mapear con la columna usando esta propiedad.
Sino se asigna informacin a la propiedad DataPropertyName ese campo no cargara datos alguno,
lo cual puede ser interesante para campos calculados como veremos en ejemplo mas adelante.
Es importante adems que la propiedad AutoGenerateColumns sea establecida en false cuando se
definan las columnas en tiempo de diseo, ya que en caso de no hacerlo se aadir a la grilla las
columnas generadas en runtime, lo cual no es deseable en este caso.
Empezaremos por cargar la informacin en un ejemplo simple, en este solo se tendr un nico
campo del tipo combobox en el columna del DataGridView.
En este caso se trata de una grilla de producto con sus precios unitarios, adems cada producto
pertenece a una marca especifica, que podr seleccionarse entre las disponibles por el sistema.
Los pasos a seguir sern:
- se recuperara la columna que fue definida del tipo combobox a la cual se le asignaran los datos a
desplegar, en este caso sern las Marcas disponibles.
- y por ultimo se cargara la grilla con los datos de los Productos.
El formulario que visualizara ser el siguiente:
Es interesante notar que la primer parte se recupera la columna del DataGridView que define el
combobox, la cual se programa como si se tratara de un combobox normal de .net, utilizando las
propiedades DataSource, a la cual se le asignado el origen de datos con la lista de Marcas, el
DisplayMember y ValueMember, para asignar que campo de la lista de Marcas ser visible al
usuario y cual ser el id de cada tem listado.
El segunda parte carga los datos del DataGridView, tomando todos los producto a mostrar en la
grilla.
Adems se especifica la propiedad AutoGenerateColumns definiendo que solo las columnas
creadas en tiempo de diseo sern las visibles.
A continuacin se visualizara los mtodo utilizados para cargar los datos en el DataGridView
public static List<MarcaEntity> GetAllMarca()
{
string sql = @"SELECT IdMarca
,Descripcion
FROM Marcas";
List<MarcaEntity> list = new List<MarcaEntity>();
using (OleDbConnection conn = new
OleDbConnection(ConfigurationManager.ConnectionStrings["default"].ToStrin
g()))
{
OleDbCommand command = new OleDbCommand(sql, conn);
conn.Open();
OleDbDataReader reader = command.ExecuteReader();
while (reader.Read())
{
list.Add(LoadMarca(reader));
}
return list;
}
return marca;
[C#]
[VB.NET]
En este seccin se analizara como poder trabajar con un combobox que ha sido agregado a la
grilla.
En este ejemplo se agrego un atributo nuevo al producto, referido a un descuento, segn el el valor
seleccionado del combo se realizara una operacin con el mismo y el valor calculado ser
presentado en otra celda de la misma fila en donde se visualiza la informacin del producto.
El formulario ahora tomara la siguiente forma
Adems si se analiza las propiedades de la nueva columna se podr apreciar que la propiedad
DataPropertyName se le ha especificado el nombre del campo de la tabla de productos, y es el
mismo nombre de la propiedad en la clase ProductoEntity.
A diferencia el ejemplo anterior en este solo se agregaron las lnea para cargar los tems de
descuento
private void Form1_Load(object sender, EventArgs e)
{
//
// Asigno los datos del combo de marcas
//
DataGridViewComboBoxColumn comboboxColumn =
dataGridView1.Columns["Marca"] as DataGridViewComboBoxColumn;
comboboxColumn.DataSource = ProductosDAL.GetAllMarca();
comboboxColumn.DisplayMember = "Descripcion";
comboboxColumn.ValueMember = "IdMarca";
//
// Asigno los datos del combo de descuentos
//
DataGridViewComboBoxColumn dgccomboDescuento =
dataGridView1.Columns["Descuento"] as DataGridViewComboBoxColumn;
dgccomboDescuento.DataSource = ProductosDAL.GetAllDescuentos();
dgccomboDescuento.DisplayMember = "Descripcion";
dgccomboDescuento.ValueMember = "IdDescuento";
//
// bindeo los datos de los productos a la grilla
//
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = ProductosDAL.GetAllProductos();
}
Pero lo mas importante es ver como se trabaja con el combo, detectando un cambio en el tem y
realizando el calculo del descuento.
private void dataGridView1_CellValueChanged(object sender,
DataGridViewCellEventArgs e)
{
if (dataGridView1.Columns[e.ColumnIndex].Name == "Descuento")
{
//
// se obtiene el valor seleccionado en el combo
//
DataGridViewComboBoxCell combo =
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] as
DataGridViewComboBoxCell;
int idDescuento = Convert.ToInt32(combo.Value);
//
// se recupera por el id la info del descuento
//
DescuentoEntity descuento =
ProductosDAL.GetDescuentosById(idDescuento);
//
// se calcula el descuento
//
DataGridViewCell cellPrecioUnitario =
dataGridView1.Rows[e.RowIndex].Cells["Precio"];
DataGridViewCell cellPrecioFinal =
dataGridView1.Rows[e.RowIndex].Cells["PrecioFinal"];
decimal valordescontar = (descuento.Porcentaje *
Convert.ToDecimal(cellPrecioUnitario.Value)) / 100;
cellPrecioFinal.Value =
Convert.ToDecimal(cellPrecioUnitario.Value) - valordescontar;
}
}
En este caso se hizo uso del evento CellValueChange, y dentro de este se realizando las
operaciones para trabajar con el valor seleccionado del combo.
- Primeramente se valida que siempre se trabaje con la columna que uno quiere operar, en este
caso por el nombre se valida que sea la definida para el descuento. Debe recordarse que estos
eventos tambin puede disparase para la edicin de otras celdas para las dems columnas. Pero
en este caso como el calculo solo interesa hacerlo en la columna de descuento es esta la
verificada.
- Como segundo pasos se toma el id del descuento seleccionado en el combo, debe recordarse
que al momento de cargar los tems del combo, fueron los id los que se unieron a la propiedad
ValueMember.
- Con el id del descuento se accede a la base de datos para recuperar la entidad del descuento y
con esta el valor del porcentaje que ser usado en el calculo
- Por ultimo se recuperas la informacin de las celdas que restan y se procede a realizar el calculo
del porcentaje que ser desplegado en la ultima columna de la grilla.
Algo interesante a notar es que esta ultima columna que se hace llamar Precio Final no tiene
valor alguno en la propiedad DataPropertyName, es por ello que no se carga ningn valor
proveniente de la base de datos.
[C#]
[VB.NET]
Definicin de la Interfaz
Para la comunicacin eficiente de los formulario, se crearan un contrato que permitir enlazarlos
con el mnimo acoplamiento entre ellos.
interface IAddItem
{
void AddNewItem(DataGridViewRow row);
}
Como se observa el mtodo que tomara el retorno de la seleccin del tem define un
DataGridViewRow, o sea un registro completo seleccionado en la grilla del formulario hijo.
Formulario Padre
Como se observara el formulario padre que realizara la apertura debe implementar la interfaz
IAddItem definida en el punto anterior.
Formulario Hijo
Este formulario contiene la grilla con los tems que pueden ser seleccionados, los cuales a modo
de ejemplo fueron creados manualmente en un DataTable.
El punto clave aqu es el botn que enva el registro seleccionado, del datagridview del formulario
hijo al formulario padre que realizo la llamada:
private void button1_Click(object sender, EventArgs e)
{
DataGridViewRow row = this.dataGridView1.SelectedRows[0] as
DataGridViewRow;
IAddItem parent = this.Owner as IAddItem;
parent.AddNewItem(row);
this.Close();
}
Como se observa se toma la fila seleccionada, y acto seguido se llamada al mtodo de la interfaz
del formulario que realizo la llamada.
El parmetro this enviado en el mtodo Show() es justamente la propiedad Owner del formulario
hijo, y al implementar la interfaz este puede ser casteado a el tipo IAddItem sin problemas, para
luego invocar al mtodo que define.
[C#]
[VB.NET]
dataGridView1.EndEdit();
}
Como se observa mucha de la funcionalidad tiene que ver con la asignacin de los eventos que
permitirn capturar la pulsacin de la teclas definidas para que se visualice el formulario de PopUp.
En este caso si bien es posible utilizar cualquier tecla, se decidi que la combinacin de Alt + D
seria la adecuada, pero podra seleccionar la que sea necesario.
Como se observa si se detecta la pulsacin de la tecla, se crea una instancia del formulario y se
muestra en formulario modal. Al cierre del mismo se captura la propiedad con el tem elegido y se
carga en la grilla.
El formulario que se desplegara tiene un cdigo muy simple en donde simplemente al hacer
dobleclick en una de sus filas, la marcara como seleccionada y cerrar el formulario.
private void dataGridView1_CellDoubleClick(object sender,
DataGridViewCellEventArgs e)
{
DataGridViewRow row = dataGridView1.SelectedRows[0];
this.ProductSelected = new Producto()
{
IdProducto = Convert.ToInt32(row.Cells["IdProducto"].Value),
Descripcion = Convert.ToString(row.Cells["Descripcion"].Value),
Precio = Convert.ToDecimal(row.Cells["precio"].Value),
};
this.Close();
}
[C#]
[VB.NET]
En este ejemplo se toma un origen de datos con tres columnas pero solo dos sern representadas
como datos en la grilla, ya que una condicin indicara si debe
dt.Rows.Add(row);
row = dt.NewRow();
row["fracc"] = false;
row["PRESENTACI"] = "PRESENTACI 2";
row["FORM_VENT"] = "FORM_VENT 2";
dt.Rows.Add(row);
row = dt.NewRow();
row["fracc"] = false;
row["PRESENTACI"] = "PRESENTACI 3";
row["FORM_VENT"] = "FORM_VENT 3";
dt.Rows.Add(row);
row = dt.NewRow();
row["fracc"] = true;
row["PRESENTACI"] = "PRESENTACI 4";
row["FORM_VENT"] = "FORM_VENT 4";
dt.Rows.Add(row);
return dt;
}
esto es importante para poder conocer como se accede a la informacin bideada en la grilla.
Como funcionalidad adicional se permite que el usuario al marcar o desmarcar una celda esta
cambie el contenido con respecto al valor que se obtuvo al momento de bindear la fila
private void dataGridView1_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
DataGridViewColumn currentColumn =
dataGridView1.Columns[e.ColumnIndex];
if (currentColumn.Name == "Fracciona")
{
DataGridViewCheckBoxCell currentCell =
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] as
DataGridViewCheckBoxCell;
DataGridViewRow currentRow = dataGridView1.Rows[e.RowIndex];
DataRowView data = currentRow.DataBoundItem as DataRowView;
if (data == null)
return;
if (Convert.ToBoolean(currentCell.Value))
currentRow.Cells["tipoventa"].Value =
Convert.ToString(data["FORM_VENT"]);
else
currentRow.Cells["tipoventa"].Value =
Convert.ToString(data["PRESENTACI"]);
}
dataGridView1.EndEdit();
[C#]
[VB.NET]
}
Como se observa hay varios eventos asociados al DataGridView necesarios para poder controlar la
pulsacin del enter en las celdas.
Al editar la calda esta asocia el evento una clase de nombre DataGridViewTextBoxEditingControl,
la cual representa un TextBox control asociado a una DataGridViewTextBoxCell.
Se vera adems que se realiza una operacin de bsqueda, en este caso para simplificar el
ejemplo se realiza sobre un datatable cargado previamente, para lo cual se ha utilizado LinQ
[C#]
Introduccin
Este es un ejemplo de cmo utilizar el componente Listview de CSharp. En este
artculo te muestro como agregar y eliminar datos a dicho componente, y tambin el
uso de TimeSpan, que en este ejemplo lo utilizo para calcular la edad.
Bueno espero que les sea de su utilidad.
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication2
{
public partial class FrmListView : Form
{
public FrmListView()
{
InitializeComponent();
}
//El Label lblcodigo est oculto, y en su propiedad text colocar 1 para
poder generar
//el cdigo...
private void btnagregar_Click(object sender, EventArgs e)
{
int edad;
string f1;
f1 = dtfecnaci.Value.ToShortDateString();
TimeSpan diferencia =
Convert.ToDateTime(DateTime.Now.ToShortDateString())
- Convert.ToDateTime(f1);
edad = Convert.ToInt16(diferencia.Days.ToString()) / 365; //aca
obtengo la edad
ListViewItem elemeneto = new ListViewItem();
elemeneto = listView1.Items.Add(lblcodigo.Text);
elemeneto.SubItems.Add(txtapellidos.Text);
elemeneto.SubItems.Add(txtnombres.Text);
elemeneto.SubItems.Add(edad.ToString());
elemeneto.SubItems.Add(txtelefono.Text);
elemeneto.SubItems.Add(cbosexo.Text);
Limpiar();
GeneraCodigo();
}
if (listView1.Items.Count>0)
{
listView1.Items.Remove(listView1.Items[numindex]);
}
if (Convert.ToInt16(listView1.Items.Count) == 0)
{
lblcodigo.Text = "1";
}
}
private void button1_Click(object sender, EventArgs e)
{
this.Close();
}
}
}