0% encontró este documento útil (0 votos)
1K vistas

C# DataGridView

El documento describe cómo hacer que las celdas de texto en un DataGridView siempre estén en mayúsculas. Explica usar el evento EditingControlShowing para detectar cuando una celda entra en modo de edición y asignar un controlador de eventos KeyPress que convierte el carácter ingresado a mayúsculas. También describe declarar la celda en edición como una variable global para evitar problemas al asignar el controlador de eventos.
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
1K vistas

C# DataGridView

El documento describe cómo hacer que las celdas de texto en un DataGridView siempre estén en mayúsculas. Explica usar el evento EditingControlShowing para detectar cuando una celda entra en modo de edición y asignar un controlador de eventos KeyPress que convierte el carácter ingresado a mayúsculas. También describe declarar la celda en edición como una variable global para evitar problemas al asignar el controlador de eventos.
Derechos de autor
© © All Rights Reserved
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 28

DataGridView

[DataGridView] Texto Celdas en Mayscula


Introduccin
En algunos casos es necesario que la entrada de datos sea siempre en mayscula,
lograr esto en un control Textbox es relativamente simple, ya que se dispone del
evento KeyPress para detectar y convertir el valor ingresado. Pero que sucede si esto
mismo se quiere aplicar a las celdas de un DataGridView, bien este articulo demuestra
como poder lograrlo.

Usando el evento EditingControlShowing
En el ejemplo se har uso del evento que permitir detecta cuando una celda entra en
modo de edicin. Dentro del evento EditingControlShowing, se detecta si la columna
que entro en modo de edicin corresponde a la que se quiere controlar. En este
ejemplo solo la columna Descripcion ser afectada con el control en el input de
datos. Es necesario remarcar que al momento de adjunta el evento KeyPress al objeto
e.Control, (que ha sido casteado a DataGridViewTextBoxEditingControl, para su
correcta utilizacin), el handler del evento se aplicara a todas las celdas de este
mismo tipo. Tambin a las de las columnas que no se quiere aplicar el control de
maysculas, en este caso la de Cuenta.
Es por eso que en el evento KeyPress tambin se control la columna que esta activa en
ese momento.
El handler del evento queda adjunto aun cuando se sale de modo edicin.
La utilizacin de la primer lnea que quita el hadler al entrar en edicin:
dText.KeyPress -= new KeyPressEventHandler(dText_KeyPress);
Solo sirve para que se adjunte un nico evento, ya que sino estuviera se adjuntaran
una detrs de otro producindose mltiples llamadas al evento KeyPress.
[C#]
01.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
02.{
03.int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
04.
05.if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
06.{
07.DataGridViewTextBoxEditingControl dText = (DataGridViewTextBoxEditingControl)e.Control;
08.
09.dText.KeyPress -= new KeyPressEventHandler(dText_KeyPress);
10.dText.KeyPress += new KeyPressEventHandler(dText_KeyPress);
11.}
12.}
13.
14.void dText_KeyPress(object sender, KeyPressEventArgs e)
15.{
16.int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
17.
18.if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
19.{
20.e.KeyChar = char.ToUpper(e.KeyChar);
21.}
22.}
Resolucin del problema en al asignacin del evento
El problema comentado anteriormente podras resolverse fcilmente con solo declarar
la variable que contendr la celda en edicin de forma global al evento.
De esta forma se podras hacer uso del evento que detecta cuando una celda ha
dejado de editarse, removiendo el handler del evento.
Ahora el evento KeyPress no controla que columna se esta editando, esto solo se hace
cuando se entra o sale del modo edicin de la celda.
[C#]
01.DataGridViewTextBoxEditingControl dText = null;
02.
03.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
04.{
05.int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
06.
07.if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
08.{
09.dText = (DataGridViewTextBoxEditingControl)e.Control;
10.
11.dText.KeyPress += new KeyPressEventHandler(dText_KeyPress);
12.}
13.}
14.
15.private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
16.{
17.int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
18.
19.if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
20.{
21.dText.KeyPress -= new KeyPressEventHandler(dText_KeyPress);
22.}
23.}
24.
25.void dText_KeyPress(object sender, KeyPressEventArgs e)
26.{
27.e.KeyChar = char.ToUpper(e.KeyChar);
28.}

C# - [DataGridView] DataGridViewComboBoxColumn
Variar contenido del combobox respecto a la fila

Introduccin
El objetivo del artculo 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.

01.private void frmSucursales_Load(object sender, EventArgs e)
02.{
03.SucursalesEntities sucursalesContext = new SucursalesEntities();
04.
05.dgvScursales.AutoGenerateColumns=false;
06.dgvScursales.DataSource = sucursalesContext.Sucursales;
07.
08.//
09.// Luego de bindear la grilla, cargo el contenido de cada fila
10.// en el combo de telefonos para cada sucursal
11.//
12.LoadGrillaComboBoxTelefonos();
13.
14.}
15.
16.private void LoadGrillaComboBoxTelefonos()
17.{
18.foreach (DataGridViewRow row in dgvScursales.Rows)
19.{
20.int idSucursal = Convert.ToInt32(row.Cells["IdSucursal"].Value);
21.
22.DataGridViewComboBoxCell comboboxCell =
row.Cells["Telefonos"] asDataGridViewComboBoxCell;
23.
24.SucursalesEntities sucursalesContext = new SucursalesEntities();
25.
26.comboboxCell.DataSource = sucursalesContext.Telefonos.Where(x => x.IdSucursal ==
idSucursal);
27.comboboxCell.ValueMember = "Id";
28.comboboxCell.DisplayMember = "Numero";
29.
30.}
31.}

Algunos Comentarios
Durante la realizacin del ejemplo se realizaron varias pruebas, con algunos eventos
que se adaptaran a la situacin y evitaran tener que recorrer en un foreach cada
registro del DataGridView.
Despus de investigar un poco los nicos dos eventos que se adaptaran a este caso
serian el RowsAdded y el CellFormatting, pero ambos trajeron problemas, lo que
impidi su uso.
El CellFormatting, tiene como problema que se ejecuta contantemente, ya que es
lanzado al redibujar la celda, y como esta operacin requiere la consulta a los datos,
generaba un efecto de bloqueo en la pantalla, el cual no es deseado.
El RowsAdded, si bien se ejecuta por cada fila agregada en la operacin de bindeo de
los datos, no haba forma interna en el evento de detectar que fila se estaba
agregando, ya que el argumento del evento e.RowIndex o e.RowCount, no devuelven
un valor correcto.
Como conclusin se dejo de lado los eventos y se hizo uso del foreach, implementado
esto en un mtodo, cuya utilizacin se realiza luego que se bindearon los datos en el
control.

C# - [DataGridView] Pasar Registros entre Grillas

Introduccin

El articulo explica de que forma se puede seleccionar registros en el control
DataGridView y pasarlos a otro, representando este la seleccin de las filas por el
usuario.
En uno de los DataGridView se listaran productos, y por medio de un checkbox en cada
fila, se podr seleccionar que tems se desean seleccionar. Botones que indican la
direccin sern los encargados de ejecutar la opcin de pasaje.
El diseo de la interfaz puede apreciarse en esta imagen:


Carga de la lista de productos

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.
01.private void frmPedidos_Load(object sender, EventArgs e)
02.{
03.//
04.// Se recupera los datos de los productos desde la tabla
05.//
06.dtoProductos datos = ProductoDAL.ProductosGetAll();
07.
08.//
09.// Se bindean los datos a la grilla
10.//
11.dgvProductos.AutoGenerateColumns = false;
12.dgvProductos.DataSource = datos;
13.dgvProductos.DataMember = "Productos";
14.
15.}
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.
01.private void btnSeleccionar_Click(object sender, EventArgs e)
02.{
03.//
04.// Se define una lista temporal de registro seleccionados
05.//
06.List<DataGridViewRow> rowSelected = new List<DataGridViewRow>();
07.
08.//
09.// Se recorre ca registro de la grilla de origen
10.//
11.foreach (DataGridViewRow row in dgvProductos.Rows)
12.{
13.//
14.// Se recupera el campo que representa el checkbox, y se valida la seleccion
15.// agregandola a la lista temporal
16.//
17.DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"]
asDataGridViewCheckBoxCell;
18.
19.if Convert.ToBoolean(cellSelecion.Value))
20.{
21.rowSelected.Add(row);
22.}
23.}
24.
25.//
26.// Se agrega el item seleccionado a la grilla de destino
27.// eliminando la fila de la grilla original
28.//
29.foreach DataGridViewRow row in rowSelected)
30.{
31.dgvSeleccion.Rows.Add(new object[] {false,
32.row.Cells["Descripcion"].Value,
33.row.Cells["PrecioUnitario"].Value,
34.row.Cells["UnidadMedida"].Value});
35.
36.dgvProductos.Rows.Remove(row);
37.}
38.
39.}
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.
Este punto lo he explicado con mas detalle siguiente articulo:
Eliminar tems en una lista

Seleccin de un tem en la grilla de destino

Ahora le toca el turno a la operacin contraria, y aqu hay un punto que ya se
mencion en el paso previo, la lista de origen est 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.

01.private void btnQuitar_Click(object sender, EventArgs e)
02.{
03.//
04.// Se define una lista temporal de registro seleccionados
05.//
06.List<DataGridViewRow> rowSelected = new List<DataGridViewRow>();
07.
08.//
09.// Se recorre cada fila de la grilla de seleccion y se determian que registros estan
checkeados
10.//
11.foreach (DataGridViewRow row in dgvSeleccion.Rows)
12.{
13.DataGridViewCheckBoxCell cellSelecion = row.Cells["SeleccionSel"]
asDataGridViewCheckBoxCell;
14.
15.if (Convert.ToBoolean(cellSelecion.Value))
16.{
17.rowSelected.Add(row);
18.}
19.}
20.
21.//
22.// Se valida si hay algun registro por eliminar
23.//
24.if (rowSelected.Count > 0)
25.{
26.//
27.// Se recupera el origen de datos que tiene asignada la grilla de productos
28.//
29.dtoProductos datos = dgvProductos.DataSource as dtoProductos;
30.
31.//
32.// Se recorre cada item seleccionado y se arma programaticamente la fila del DataTable
33.// se elimina el registro de la grilla de selecciones
34.//
35.foreach (DataGridViewRow row in rowSelected)
36.{
37.
38.dtoProductos.ProductosRow productoRow = datos.Productos.NewProductosRow();
39.
40.productoRow.Descripcion = Convert.ToString(row.Cells["DescripcionSel"].Value);
41.productoRow.PrecioUnitario = Convert.ToDecimal(row.Cells["PrecioUnitarioSel"].Value);
42.productoRow.UnidadMedida = Convert.ToString(row.Cells["UnidadMedidaSel"].Value);
43.datos.Productos.Rows.Add(productoRow);
44.
45.dgvSeleccion.Rows.Remove(row);
46.}
47.
48.//
49.// Se binden los datos nuevamente, pero ahora con los nuevos registros
50.// agregados del paso anterior
51.//
52.dgvProductos.AutoGenerateColumns = false;
53.dgvProductos.DataSource = datos;
54.dgvProductos.DataMember = "Productos";
55.}
56.}
Es necesario analizar como toma los datos originales convirtiendo el contenido de
DataSource de la grilla, en este caso a dtoProductos, ya que este es el tipo de datos
utilizado en al carga original. Se toman los datos originales, se procede a la creacin
de cada row de forma programtica, asignando el valor a cada campo, por ultimo se
vuelve a bindear la grilla.

C# - [DataGridView] Uso del CheckBox -
DataGridViewCheckBoxColumn

Introduccin
El articulo intentara mostrar las algunas forma en que se puede utilizar el checkbox en
un control DataGridView.
Detectar el cambio en la seleccin
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.
01.private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
02.{
03.//
04.// Solo se trabaja ante los cambios en la columan de los checkbox
05.//
06.if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion") {
07.//
08.// Se toma la fila seleccionada
09.//
10.DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
11.
12.//
13.// Se selecciona la celda del checkbox
14.//
15.DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"]
asDataGridViewCheckBoxCell;
16.
17.//
18.// Se valida si esta checkeada
19.//
20.if (Convert.ToBoolean(cellSelecion.Value)) {
21.
22.string mensaje = string.Format("Evento CellValueChanged.\n\nSe ha seccionado,
\nDescripcion: '{0}', \nPrecio Unitario: '{1}', \nMedida: '{2}'",
23.row.Cells["Descripcion"].Value,
24.row.Cells["PrecioUnitario"].Value,
25.row.Cells["UnidadMedida"].Value);
26.
27.MessageBox.Show(mensaje, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
28.
29.}
30.
31.}
32.
33.}
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.
01.private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
02.{
03.//
04.// Detecta si se ha seleccionado el header de la grilla
05.//
06.if (e.RowIndex == -1)
07.return;
08.
09.if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion")
10.{
11.
12.//
13.// Se toma la fila seleccionada
14.//
15.DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
16.
17.//
18.// Se selecciona la celda del checkbox
19.//
20.DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"]
asDataGridViewCheckBoxCell;
21.
22.
23.if (Convert.ToBoolean(cellSelecion.Value))
24.{
25.
26.string mensaje = string.Format("Evento CellContentClick.\n\nSe ha seccionado,
\nDescripcion: '{0}', \nPrecio Unitario: '{1}', \nMedida: '{2}'",
27.row.Cells["Descripcion"].Value,
28.row.Cells["PrecioUnitario"].Value,
29.row.Cells["UnidadMedida"].Value);
30.
31.MessageBox.Show(mensaje, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
32.
33.}
34.else
35.{
36.string mensaje = string.Format("Evento CellContentClick.\n\nSe ha quitado la seleccion,
\nDescripcion: '{0}', \nPrecio Unitario: '{1}', \nMedida: '{2}'",
37.row.Cells["Descripcion"].Value,
38.row.Cells["PrecioUnitario"].Value,
39.row.Cells["UnidadMedida"].Value);
40.
41.MessageBox.Show(mensaje, "", MessageBoxButtons.OK, MessageBoxIcon.Information);
42.
43.}
44.}
45.}
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
1.private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
2.{
3.if (dataGridView1.IsCurrentCellDirty)
4.{
5.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
6.}
7.}
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

Aplicar formato a la seleccin
Teniendo en cuenta lo contado en la seccin anterior, aplicar un formato a la fila
seleccionada no debera ser un misterio.
01.private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
02.{
03.//
04.// Detecta si se ha seleccionado el header de la grilla
05.//
06.if (e.RowIndex == -1)
07.return;
08.
09.if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion")
10.{
11.
12.//
13.// Se toma la fila seleccionada
14.//
15.DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
16.
17.//
18.// Se selecciona la celda del checkbox
19.//
20.DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"]
asDataGridViewCheckBoxCell;
21.
22.if (Convert.ToBoolean(cellSelecion.Value))
23.row.DefaultCellStyle.BackColor = Color.Green;
24.else
25.row.DefaultCellStyle.BackColor = Color.White;
26.
27.}
28.}
29.
30.private void dataGridView1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
31.{
32.if (dataGridView1.IsCurrentCellDirty)
33.{
34.dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
35.}
36.}
Simplemente ante la deteccin de la seleccin del usuario se cambia el color de la fila
usando el DefaultCellStyle.BackColor.

C# - [Winforms] Seleccionar Fila con ENTER
DataGridView y ListView

Introduccin
Este articulo es mostrara una alternativa de como se puede detectar la presin de una
tecla (en este caso el ENTER) en un control determinado, pudiendo as trabajar con la
seleccin.
En el ejemplo se trabajar con dos controles, el DataGridView y un ListView.
Bsicamente la tcnica para ambos ejemplos ser similar, todo el trabajo se realizara
en el mtodo ProcessCmdKey del formulario, (el cual es una sobrecarga), permitiendo
atrapar la teclas pulsadas en el formulario, en este adems se podras validar que
control esta activo en ese momento y en caso de ser el que resulta til, procede a
trabajar con la seleccin.
Para ambos ejemplo se permitir optar (mediante radiobuttons) si la seleccin del tem
en la lista se mostrar en un mensaje, o ser desplegado en otra ventana (formulario).

DataGridView - Seleccin de la fila
Como haba comentado todo el trabajo esta en la funcin:
[C#]
01.protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg,
System.Windows.Forms.Keys keyData)
02.{
03.//
04.// Si el control DataGridView no tiene el foco,
05.// se abandonamos el procedimiento, llamando al metodo base
06.//
07.if ((!dataGridView1.Focused))
08.return base.ProcessCmdKey(ref msg, keyData);
09.
10.//
11.// Si la tecla presionada es distinta al ENTER,
12.// se abandonamos el procedimiento, llamando al metodo base
13.//
14.if (keyData != Keys.Enter)
15.return base.ProcessCmdKey(ref msg, keyData);
16.//
17.// Obtenemos la fila actual
18.//
19.DataGridViewRow row = dataGridView1.CurrentRow;
20.
21.if (rbMostrarMensaje.Checked)
22.{
23.MessageBox.Show(string.Format("Se ha seleccionado, Cuenta:'{0}' Descripcion:'{1}'",
24.row.Cells["cuenta"].Value,
25.row.Cells["descripcion"].Value));
26.}
27.else if (rbMostrarForm.Checked)
28.{
29.int cuenta = Convert.ToInt32(row.Cells["cuenta"].Value);
30.string desc = Convert.ToString(row.Cells["descripcion"].Value);
31.
32.frmSeleccion frm = new frmSeleccion(cuenta, desc);
33.frm.ShowDialog();
34.}
35.
36.return true;
37.}
- 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.


ListView Seleccin de la fila
La nica diferencia entre este cdigo y el usado en el DataGridview, ser la forma en
que se obtiene el tem seleccionado.
Las validaciones en cuanto a la tecla presionada, y el foco en el control activo son
idnticas para ambos casos.
[C#]
01.protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg,
System.Windows.Forms.Keys keyData)
02.{
03.//
04.// Si el control DataGridView no tiene el foco,
05.// se abandonamos el procedimiento, llamando al metodo base
06.//
07.if ((!listView1.Focused))
08.return base.ProcessCmdKey(ref msg, keyData);
09.
10.//
11.// Si la tecla presionada es distinta al ENTER,
12.// se abandonamos el procedimiento, llamando al metodo base
13.//
14.if (keyData != Keys.Enter)
15.return base.ProcessCmdKey(ref msg, keyData);
16.
17.//
18.// Sino hay item seleccinado en la lista
19.// se abandonamos el procedimiento, llamando al metodo base
20.//
21.if(listView1.SelectedItems.Count == 0)
22.return base.ProcessCmdKey(ref msg, keyData);
23.
24.//
25.// Obtenemos la fila actual
26.//
27.ListViewItem item = listView1.SelectedItems[0];
28.
29.if (rbMostrarMensaje.Checked)
30.{
31.MessageBox.Show(string.Format("Se ha seleccionado, Cuenta:'{0}' Descripcion:'{1}'",
32.item.Text,
33.item.SubItems[1].Text));
34.}
35.else if (rbMostrarForm.Checked)
36.{
37.int cuenta = Convert.ToInt32(item.Text);
38.string desc = Convert.ToString(item.SubItems[1].Text);
39.
40.frmSeleccion frm = new frmSeleccion(cuenta, desc);
41.frm.ShowDialog();
42.}
43.
44.return true;
45.}

[DataGridView] - ComboBox y evento
SelectedIndexChanged

Introduccin

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.




Planteo del problema

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.

Primer planteo de solucin

Para resolver el problema sern necesarios dos eventos:
- EditingControlShowing, el cual se lanza cuando la celda entre en estado de edicin
- SelectedIndexChanged, el cual ser asignado al control combo de la celda que se
este editando

01.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
02.{
03.DataGridViewComboBoxEditingControl dgvCombo = e.Control
asDataGridViewComboBoxEditingControl;
04.
05.if (dgvCombo != null)
06.{
07.//
08.// se remueve el handler previo que pudiera tener asociado, a causa ediciones previas de
la celda
09.// evitando asi que se ejecuten varias veces el evento
10.//
11.dgvCombo.SelectedIndexChanged -= new EventHandler(dvgCombo_SelectedIndexChanged);
12.
13.dgvCombo.SelectedIndexChanged += newEventHandler(dvgCombo_SelectedIndexChanged);
14.}
15.
16.}
17.
18.private void dvgCombo_SelectedIndexChanged(object sender, EventArgs e)
19.{
20.//
21.// se recupera el valor del combo
22.// a modo de ejemplo se escribe en consola el valor seleccionado
23.//
24.ComboBox combo = sender as ComboBox;
25.
26.Console.WriteLine(combo.SelectedValue);
27.
28.//
29.// se accede a la fila actual, para trabajr con otor de sus campos
30.// en este caso se marca el check si se cambia la seleccion
31.//
32.DataGridViewRow row = dataGridView1.CurrentRow;
33.
34.DataGridViewCheckBoxCell cell = row.Cells["Seleccionado"] asDataGridViewCheckBoxCell;
35.cell.Value = true;
36.}

Aqu hay algunos puntos a detallar:
- Como se observa en el evento EditingControlShowing, este tiene un argumento en el
evento que permite tomar que control esta siendo editado, puntualmente el e.Control,
el cual puede ser convertido a un tipo especifico se quiere trabajar, en este caso el
combobox, cualquier otra celda no ser del mismo tipo por lo tanto la conversin
devolver null.
Vale aclarar que en este caso usar esta lnea:
DataGridViewComboBoxEditingControl dgvCombo = e.Control as
DataGridViewComboBoxEditingControl;
o esta otra:
ComboBox dgvCombo = e.Control as ComboBox;
es indiferente, con ambas funciona correctamente.
- Seguramente se preguntaran porque se esta realizando la desasignacin del evento,
cuando en la lnea siguiente se vuelve adjunta. Esto bsicamente se realiza porque si
en varias oportunidades es editada la misma celda, en cada ingreso al evento se
asignara un nuevo handler, o sea no es pisado el previo o existente, provocando que
se lance mas de una vez el mismo evento, lo cual no es el efecto deseado.
- En este ejemplo no se hizo, pero podra haberse preguntado si el control en edicin
es del tipo ComboBox, mediante el agregado de if, y el uso del is, para luego en caso
de ser afirmativo en ese caso si convertir al tipo necesario.
01.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
02.{
03.if (e.Control is ComboBox)
04.{
05.DataGridViewComboBoxEditingControl dgvCombo = e.Control
asDataGridViewComboBoxEditingControl;
06.
07.//
08.// se remueve el handler previo que pudiera tener asociado, a causa ediciones previas de
la celda
09.// evitando asi que se ejecuten varias veces el evento
10.//
11.dgvCombo.SelectedIndexChanged -= new EventHandler(dvgCombo_SelectedIndexChanged);
12.
13.dgvCombo.SelectedIndexChanged += newEventHandler(dvgCombo_SelectedIndexChanged);
14.}
15.
16.}


Problema detectado en la primer solucin

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.

Segundo Planteo de solucin

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.

01.DataGridViewComboBoxEditingControl dgvCombo;
02.
03.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
04.{
05.dgvCombo = e.Control as DataGridViewComboBoxEditingControl;
06.
07.if (dgvCombo != null)
08.{
09.dgvCombo.SelectedIndexChanged += newEventHandler(dvgCombo_SelectedIndexChanged);
10.}
11.
12.}
13.
14.private void dvgCombo_SelectedIndexChanged(object sender, EventArgs e)
15.{
16.//
17.// se recupera el valor del combo
18.// a modo de ejemplo se escribe en consola el valor seleccionado
19.//
20.ComboBox combo = sender as ComboBox;
21.
22.Console.WriteLine(combo.SelectedValue);
23.
24.//
25.// se accede a la fila actual, para trabajr con otor de sus campos
26.// en este caso se marca el check si se cambia la seleccion
27.//
28.DataGridViewRow row = dataGridView1.CurrentRow;
29.
30.DataGridViewCheckBoxCell cell = row.Cells["Seleccionado"] asDataGridViewCheckBoxCell;
31.cell.Value = true;
32.}
33.
34.private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
35.{
36.
37.if (dgvCombo != null)
38.dgvCombo.SelectedIndexChanged -= newEventHandler(dvgCombo_SelectedIndexChanged);
39.
40.}

Puntos a remarcar:
- Se debe conservar el control combobox editado de forma global del formulario, de
esta forma al terminar la edicin, poder remover el evento.
Este problema se presenta ya que no existe algn otro evento en la grilla, en donde su
argumento devuelva el control que lo genera, de la misma forma en que lo hace el
evento EditingControlShowing, con su argumento e.Control
- En el evento EditingControlShowing solo hace falta agregar el handler al evento, ya
que la remocin se realiza en esta oportunidad cuando es terminada la edicin en el
eventoCellEndEdit

[DataGridView] Clculos Totales en las filas y
columnas

Introduccin

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.

Carga de los datos en la grilla

Esta ser la primer operacin ha realizar, la carga de los datos de los productos en la
grilla.
01.private void frmPedidos_Load(object sender, EventArgs e)
02.{
03.//
04.// Se recupera los datos de los productos desde la tabla
05.//
06.dtoProductos datos = ProductoDAL.ProductosGetAll();
07.
08.//
09.// Se agrega un registro adicional al DataTable, para representar la fila de totales
10.//
11.dtoProductos.ProductosRow rowTotal = datos.Productos.NewProductosRow();
12.datos.Productos.Rows.Add(rowTotal);
13.
14.//
15.// Se bindean los datos a la grilla
16.//
17.dataGridView1.AutoGenerateColumns = false;
18.dataGridView1.DataSource = datos;
19.dataGridView1.DataMember = "Productos";
20.
21.//
22.// Se selecciona la ultima fila de Totales y se marca como readonly
23.// para evitar la seleccion por el usuario
24.//
25.DataGridViewRow row = dataGridView1.Rows[dataGridView1.Rows.Count - 1];
26.row.ReadOnly = true;
27.
28.//
29.// Se asigna el evento para detectar los cambios que el usuario realice
30.//
31.dataGridView1.CellValueChanged
+=newDataGridViewCellEventHandler(dataGridView1_CellValueChanged);
32.}

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 ltima fila para evitar que el usuario la edite.
Algo a remarcar es la asignacin del evento manuablemente en la ltima 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.

01.private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
02.{
03.//
04.// Solo se trabaja ante los cambios en la columan de los checkbox
05.// y el ingreso de una canifad por el usuario
06.//
07.if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion" ||
08.dataGridView1.Columns[e.ColumnIndex].Name == "Pedido")
09.{
10.decimal totalColumna = 0;
11.
12.//
13.// Se recorre fila a fila para recalcular el total despues del cambio
14.//
15.foreach (DataGridViewRow row in dataGridView1.Rows)
16.{
17.//
18.// Se selecciona la celda del checkbox
19.//
20.DataGridViewCheckBoxCell cellSelecion = row.Cells["Seleccion"]
asDataGridViewCheckBoxCell;
21.
22.//
23.// Se valida si esta checkeada
24.//
25.if (Convert.ToBoolean(cellSelecion.Value))
26.{
27.//
28.// Se valida si el usuario ingreso un valor en la celda de pedido
29.//
30.decimal pedido = 0;
31.if (!decimal.TryParse(Convert.ToString(row.Cells["Pedido"].Value),out pedido))
32.continue;
33.
34.//
35.// Se realiza el calculo para la fila, asignado el total en la celda "Total"
36.// de la misma
37.//
38.decimal totalFila = Convert.ToDecimal(row.Cells["PrecioUnitario"].Value) * pedido;
39.row.Cells["Total"].Value = totalFila;
40.
41.//
42.// Se aumula el total de cada una de las filas
43.//
44.totalColumna += totalFila;
45.}
46.}
47.
48.//
49.// Se toma la ultima fila del total general, asignando el valor acumulado en el calculo
50.//
51.DataGridViewRow rowTotal = dataGridView1.Rows[dataGridView1.Rows.Count - 1];
52.rowTotal.Cells["Total"].Value = totalColumna;
53.
54.}
55.}
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.
01.private void dataGridView1_CellValidating(object sender,
DataGridViewCellValidatingEventArgs e)
02.{
03.if (dataGridView1.Columns[e.ColumnIndex].Name == "Pedido")
04.{
05.//
06.// Si el campo esta vacio no lo marco como error
07.//
08.if (string.IsNullOrEmpty(e.FormattedValue.ToString()))
09.return;
10.
11.//
12.// Solo se valida ante el ingreso de un valor en el campo
13.//
14.decimal pedido = 0;
15.if (!decimal.TryParse(e.FormattedValue.ToString(), out pedido))
16.{
17.DataGridViewRow row = dataGridView1.Rows[e.RowIndex];
18.row.ErrorText = "Debe ingresar un numero valido";
19.e.Cancel = true;
20.}
21.}
22.}
23.
24.//
25.// Este evento es usado al presiona ESC cancelando la edicion
26.// se elimine el mensaje de error en la fila
27.//
28.private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
29.{
30.dataGridView1.Rows[e.RowIndex].ErrorText = String.Empty;
31.}

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

[DataGridView] - Uso del
DataGridViewComboBoxColumn

Introduccin

Este articulo tendr por objetivo mostrar como trabajar con las columna del tipo
ComboBox que se encuentran dentro de una celda del datagridview.

1- Definicin de las columnas en tiempo de diseo

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

Aqu puede seleccionarse dos opciones:
- Agregar nuevas columnas a la grilla por medio de la opcin Add Column
visualizndose el siguiente cuadro:

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.

2 Asignacin de los datos a la columna DataGridViewComboBoxColumn

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:

La carga de los datos se ha realizado en el evento Load del formulario
01.private void Form1_Load(object sender, EventArgs e)
02.{
03.//
04.// Asigno los datos del combo de marcas
05.//
06.DataGridViewComboBoxColumn comboboxColumn = dataGridView1.Columns["Marca"]
asDataGridViewComboBoxColumn;
07.
08.comboboxColumn.DataSource = ProductosDAL.GetAllMarca();
09.comboboxColumn.DisplayMember = "Descripcion";
10.comboboxColumn.ValueMember = "IdMarca";
11.
12.//
13.// bindeo los datos de los productos a la grilla
14.//
15.dataGridView1.AutoGenerateColumns = false;
16.dataGridView1.DataSource = ProductosDAL.GetAllProductos();
17.
18.}
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 mtodos utilizados para cargar los datos en el
DataGridView
01.public static List<MarcaEntity> GetAllMarca()
02.{
03.string sql = @"SELECT IdMarca
04.,Descripcion
05.FROM Marcas";
06.
07.List<MarcaEntity> list = new List<MarcaEntity>();
08.
09.using (OleDbConnection conn =
newOleDbConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
10.{
11.
12.OleDbCommand command = new OleDbCommand(sql, conn);
13.
14.conn.Open();
15.
16.OleDbDataReader reader = command.ExecuteReader();
17.
18.while (reader.Read())
19.{
20.list.Add(LoadMarca(reader));
21.}
22.
23.return list;
24.}
25.}
26.
27.private static MarcaEntity LoadMarca(IDataReader reader)
28.{
29.MarcaEntity marca = new MarcaEntity();
30.
31.marca.IdMarca = Convert.ToInt32(reader["IdMarca"]);
32.marca.Descripcion = Convert.ToString(reader["Descripcion"]);
33.
34.return marca;
35.}

01.public static List<ProductoEntity> GetAllProductos()
02.{
03.string sql = @"SELECT [IdProducto]
04.,[IdMarca]
05.,[Descripcion]
06.,[PrecioUnitario]
07.FROM Productos";
08.
09.List<ProductoEntity> list = new List<ProductoEntity>();
10.
11.using (OleDbConnection conn =
newOleDbConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
12.{
13.
14.OleDbCommand command = new OleDbCommand(sql, conn);
15.
16.conn.Open();
17.
18.OleDbDataReader reader = command.ExecuteReader();
19.
20.while (reader.Read())
21.{
22.list.Add(LoadProducto(reader));
23.}
24.
25.return list;
26.}
27.
28.
29.}
30.
31.private static ProductoEntity LoadProducto(IDataReader reader)
32.{
33.ProductoEntity producto = new ProductoEntity();
34.
35.producto.IdProducto = Convert.ToInt32(reader["IdProducto"]);
36.
37.producto.IdMarca = Convert.ToInt32(reader["IdMarca"]);
38.producto.Descripcion = Convert.ToString(reader["Descripcion"]);
39.
40.producto.PrecioUnitario = Convert.ToDecimal(reader["PrecioUnitario"]);
41.
42.return producto;
43.}


3 Realizar una operacin al cambiar la seleccin del combo

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
01.private void Form1_Load(object sender, EventArgs e)
02.{
03.//
04.// Asigno los datos del combo de marcas
05.//
06.DataGridViewComboBoxColumn comboboxColumn = dataGridView1.Columns["Marca"]
asDataGridViewComboBoxColumn;
07.
08.comboboxColumn.DataSource = ProductosDAL.GetAllMarca();
09.comboboxColumn.DisplayMember = "Descripcion";
10.comboboxColumn.ValueMember = "IdMarca";
11.
12.//
13.// Asigno los datos del combo de descuentos
14.//
15.DataGridViewComboBoxColumn dgccomboDescuento = dataGridView1.Columns["Descuento"] as
DataGridViewComboBoxColumn;
16.
17.dgccomboDescuento.DataSource = ProductosDAL.GetAllDescuentos();
18.dgccomboDescuento.DisplayMember = "Descripcion";
19.dgccomboDescuento.ValueMember = "IdDescuento";
20.
21.//
22.// bindeo los datos de los productos a la grilla
23.//
24.dataGridView1.AutoGenerateColumns = false;
25.dataGridView1.DataSource = ProductosDAL.GetAllProductos();
26.
27.}
Pero lo mas importante es ver como se trabaja con el combo, detectando un cambio en
el tem y realizando el calculo del descuento.
01.private void dataGridView1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
02.{
03.
04.if (dataGridView1.Columns[e.ColumnIndex].Name == "Descuento")
05.{
06.//
07.// se obtiene el valor seleccionado en el combo
08.//
09.DataGridViewComboBoxCell combo = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex]
asDataGridViewComboBoxCell;
10.
11.int idDescuento = Convert.ToInt32(combo.Value);
12.
13.//
14.// se recupera por el id la info del descuento
15.//
16.DescuentoEntity descuento = ProductosDAL.GetDescuentosById(idDescuento);
17.
18.//
19.// se calcula el descuento
20.//
21.DataGridViewCell cellPrecioUnitario = dataGridView1.Rows[e.RowIndex].Cells["Precio"];
22.DataGridViewCell cellPrecioFinal = dataGridView1.Rows[e.RowIndex].Cells["PrecioFinal"];
23.
24.decimal valordescontar = (descuento.Porcentaje *
Convert.ToDecimal(cellPrecioUnitario.Value)) / 100;
25.
26.cellPrecioFinal.Value = Convert.ToDecimal(cellPrecioUnitario.Value) - valordescontar;
27.}
28.}
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.

[DataGridView] Parte 3 Pasaje de informacin entre
grillas en distintos formulario

Introduccin
Este artculo es consecuencia de otros descriptos con anterioridad
C# Comunicar formularios de forma desacoplada
Como se habr visto comunicar formularios de forma desacoplada puede no se tan
simple alguna veces y es justamente cuando se hace uso de informacin entre grillas
que la situacin puede ser algo mas compleja
Este ejemplo intenta demostrar como realizar la comunicacin y desde un formulario
hijo pasar informacin de tems seleccionados al un formulario padre o quien realiza la
llamada.
Definicin de la Interfaz
Para la comunicacin eficiente de los formulario, se crearan un contrato que permitir
enlazarlos con el mnimo acoplamiento entre ellos.
1.interface IAddItem
2.{
3.void AddNewItem(DataGridViewRow row);
4.}
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.

01.public partial class Form1 : Form, IAddItem
02.{
03.public Form1()
04.{
05.InitializeComponent();
06.}
07.
08.private void button1_Click(object sender, EventArgs e)
09.{
10.Form2 formAdd = new Form2();
11.formAdd.Show(this);
12.
13.}
14.
15.#region IAddItem Members
16.
17.public void AddNewItem(DataGridViewRow row)
18.{
19.string item = row.Cells["item"].Value.ToString();
20.string desc = row.Cells["Desc"].Value.ToString();
21.
22.this.dataGridView1.Rows.Add(new []{ item, desc });
23.
24.}
25.
26.#endregion
27.
28.
29.}

Es importante destacar algunas lneas:
- Lnea 11: es el punto en donde se realiza la apertura del forma hijo, y es all donde
se le indica quien es el padre o quien esta realizando al apertura del formulario, esto
se esta indicando al hacer uso del this en el parmetro del mtodo Show()
- Lneas 17-24: en estas lnea de cdigo se estar tomando la fila que se retorna de la
seleccin, se recupera cada valor y se arma el nuevo registro, en este punto en caso
de que fuera necesario se podra realizar clculos o modificar los datos, para ser luego
insertados en la grilla de tems seleccionados.
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:
01.private void button1_Click(object sender, EventArgs e)
02.{
03.DataGridViewRow row = this.dataGridView1.SelectedRows[0] as DataGridViewRow;
04.
05.
06.IAddItem parent = this.Owner as IAddItem;
07.parent.AddNewItem(row);
08.
09.this.Close();
10.}
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.


[DataGridView] Parte 2 Edicin de celda con form
PopUp para la seleccin de tem - KeyDown

El objetivo del articulo es demostrar como en la edicin de la celda se puede lanzar un
formulario de bsqueda para la seleccin de un tem determinado, y a retorno del
mismo completar la informacin de la fila en edicin con la seleccin del formulario.
Para esta operacin se hace uso de propiedades, y clases las cuales permitirn
desacoplar ambas grilla, tanto la que originalmente mantiene la lista de productos
seleccionados, como la que se despliega y permite la eleccin de un tem determinado.
En el formulario cuyo objetico ser llevar la lista de tems elegidos por el usuario se
dispone de siguiente cdigo.
01.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
02.{
03.DataGridViewTextBoxEditingControl dText = (DataGridViewTextBoxEditingControl)e.Control;
04.
05.dText.KeyDown -= new KeyEventHandler(dText_KeyDown);
06.dText.KeyDown += new KeyEventHandler(dText_KeyDown);
07.}
08.
09.void dText_KeyDown(object sender, KeyEventArgs e)
10.{
11.int rowIndex =
((System.Windows.Forms.DataGridViewTextBoxEditingControl)(sender)).EditingControlRowIndex;
12.
13.if (e.Alt && e.KeyCode == Keys.D)
14.{
15.frmSeleccionarProducto form = new frmSeleccionarProducto();
16.
17.form.ShowDialog();
18.
19.Producto productoSeleccionado = form.ProductSelected;
20.
21.DataGridViewRow row = dataGridView1.Rows[rowIndex];
22.row.Cells["IdProducto"].Value = productoSeleccionado.IdProducto;
23.row.Cells["Descripcion"].Value = productoSeleccionado.Descripcion;
24.row.Cells["precio"].Value = productoSeleccionado.Precio;
25.
26.dataGridView1.EndEdit();
27.}
28.}
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.
01.private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
02.{
03.DataGridViewRow row = dataGridView1.SelectedRows[0];
04.
05.this.ProductSelected = new Producto()
06.{
07.IdProducto = Convert.ToInt32(row.Cells["IdProducto"].Value),
08.Descripcion = Convert.ToString(row.Cells["Descripcion"].Value),
09.Precio = Convert.ToDecimal(row.Cells["precio"].Value),
10.};
11.
12.this.Close();
13.}





[DataGridView] Parte 1 Valor de celda Condicional
usando CellFormatting

El ejemplo intenta demostrar como una vez que se bindean los datos estos pueden ser
acomodados en las celda segn cierta condicin.
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

01.private void dataGridView1_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
02.{
03.DataGridViewColumn currentColumn = dataGridView1.Columns[e.ColumnIndex];
04.
05.if (currentColumn.Name == "Fracciona")
06.{
07.DataGridViewRow currentRow = dataGridView1.Rows[e.RowIndex];
08.DataRowView data = currentRow.DataBoundItem as DataRowView;
09.
10.if (data == null)
11.return;
12.
13.if(Convert.ToBoolean(data["fracc"]))
14.currentRow.Cells["tipoventa"].Value = Convert.ToString(data["FORM_VENT"]);
15.else
16.currentRow.Cells["tipoventa"].Value = Convert.ToString(data["PRESENTACI"]);
17.
18.}
19.}
En este caso la lgica principal se encuentra en el evento CellFormatting, pues este
ser el encargado de realiza la lgica necesaria para decidir que campo de los datos
bindeados deben representarse en la celda.
Se podr visualizar que un campo que si se ha enlazado a la grilla mediante la
propiedadDataPropertyName pero el segunda columnas de la grilla no se le ha
asignado este valor ya que ser por medio de cdigo quien decida que valor mostrar.
Una de las lneas mas importantes es la 7, ya que esta permite recuperar los datos
originales que se estn bindeando a esa fila en particular, y por lo tanto trabajar con
ellos.
Los datos utilizados para el ejemplo son los siguiente
01.private DataTable GetDataTable()
02.{
03.DataTable dt = new DataTable();
04.
05.dt.Columns.Add("fracc", typeof(bool));
06.dt.Columns.Add("PRESENTACI");
07.dt.Columns.Add("FORM_VENT");
08.
09.
10.DataRow row = dt.NewRow();
11.row["fracc"] = true;
12.row["PRESENTACI"] = "PRESENTACI 1";
13.row["FORM_VENT"] = "FORM_VENT 1";
14.dt.Rows.Add(row);
15.
16.row = dt.NewRow();
17.row["fracc"] = false;
18.row["PRESENTACI"] = "PRESENTACI 2";
19.row["FORM_VENT"] = "FORM_VENT 2";
20.dt.Rows.Add(row);
21.
22.row = dt.NewRow();
23.row["fracc"] = false;
24.row["PRESENTACI"] = "PRESENTACI 3";
25.row["FORM_VENT"] = "FORM_VENT 3";
26.dt.Rows.Add(row);
27.
28.row = dt.NewRow();
29.row["fracc"] = true;
30.row["PRESENTACI"] = "PRESENTACI 4";
31.row["FORM_VENT"] = "FORM_VENT 4";
32.dt.Rows.Add(row);
33.
34.return dt;
35.
36.}
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
01.private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
02.{
03.
04.DataGridViewColumn currentColumn = dataGridView1.Columns[e.ColumnIndex];
05.
06.if (currentColumn.Name == "Fracciona")
07.{
08.DataGridViewCheckBoxCell currentCell =
dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] asDataGridViewCheckBoxCell;
09.
10.DataGridViewRow currentRow = dataGridView1.Rows[e.RowIndex];
11.DataRowView data = currentRow.DataBoundItem as DataRowView;
12.
13.if (data == null)
14.return;
15.
16.if (Convert.ToBoolean(currentCell.Value))
17.currentRow.Cells["tipoventa"].Value = Convert.ToString(data["FORM_VENT"]);
18.else
19.currentRow.Cells["tipoventa"].Value = Convert.ToString(data["PRESENTACI"]);
20.
21.dataGridView1.EndEdit();
22.}
23.}
[DataGridView] KeyPress detectar ENTER y bsqueda

El objetivo del artculo es demostrar como mediante la edicin de una celda se puede
detectar la presin de la tecla ENTER, la cual ser capturada para realizar una
bsqueda con la informacin ingresada en la celda
Se debe aclarar que las columnas que no se requiere bsqueda deber asignarse la
propiedad readonly para evitar problemas, pues por defecto tambin entraran en la
lgica que controla la pulsacin del enter, salvo que se agregue validaciones para que
no actu sobre estas celdas.

01.private void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
02.{
03.dataGridView1.BeginEdit(false);
04.}
05.
06.private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
07.{
08.DataGridViewTextBoxEditingControl dText = (DataGridViewTextBoxEditingControl)e.Control;
09.dText.KeyUp -= new KeyEventHandler(text_KeyUp);
10.dText.KeyUp += new KeyEventHandler(text_KeyUp);
11.}
12.
13.void text_KeyUp(object sender, KeyEventArgs e)
14.{
15.int rowIndex =
((System.Windows.Forms.DataGridViewTextBoxEditingControl)(sender)).EditingControlRowIndex;
16.
17.if (e.KeyCode == Keys.Enter)
18.{
19.int valueEntered = Convert.ToInt32(dataGridView1.Rows[rowIndex -
1].Cells["cuenta"].Value);
20.
21.dataGridView1.Rows[rowIndex - 1].Cells["descripcion"].Value =this.Search(valueEntered);
22.}
23.}
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


01.private DataTable GetDataTable()
02.{
03.DataTable dt = new DataTable();
04.
05.dt.Columns.Add("cuenta");
06.dt.Columns.Add("descripcion");
07.
08.
09.DataRow row = dt.NewRow();
10.row["cuenta"] = "1001";
11.row["descripcion"] = "cuenta 1001";
12.dt.Rows.Add(row);
13.
14.row = dt.NewRow();
15.row["cuenta"] = "1002";
16.row["descripcion"] = "cuenta 1002";
17.dt.Rows.Add(row);
18.
19.row = dt.NewRow();
20.row["cuenta"] = "1003";
21.row["descripcion"] = "cuenta 1003";
22.dt.Rows.Add(row);
23.
24.return dt;
25.
26.
27.}
28.
29.private string Search(int cuenta)
30.{
31.string descripcion = (from item in this.GetDataTable().AsEnumerable()
32.where Convert.ToInt32(item["cuenta"]) == cuenta
33.select item["descripcion"].ToString()).FirstOrDefault<string>();
34.
35.return descripcion;
36.}

También podría gustarte