Sei sulla pagina 1di 51

Como puedo vaciar el contenido de un datagridview?

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();

COLOREAR CELDAS DE UN DATAGRIDVIEW


Supongamos que tenemos un control de tipo DataGridView que tiene tres
columnas visibles.
Con el siguiente mtodo vamos a poder pintar de un color determinado el
fondo de una fila determinada.
Los argumentos que recibe el mtodo son:

DataGridView visor: El visor del que deseamos pintar el fondo de una de


sus lneas

Int32 fila: El nmero de la fila que deseamos pintar el fondo

Color c: El color del que vamos a pintar el fondo de la fila

Vemos el cdigo del mtodo:


private void gestionaResaltados(DataGridView visor, Int32 fila, System.Drawing.Color c)
{
visor.Rows[fila].Cells[0].Style.BackColor = c;
visor.Rows[fila].Cells[1].Style.BackColor = c;
visor.Rows[fila].Cells[2].Style.BackColor = c;
}

DataGridView: posicionar scroll


Esta es una cuestin muy simple y sencilla pero me ha parecido correcto incluirla en un post
porque es de ese tipo de cosas que siempre se preguntan y nadie escribe sobre ello porque
parece demasiado trivial.

Supongamos el caso de un DataGridView que contiene multitud de lneas y el usuario se


desplaza por el mismo con un scroll vertical. En un momento dado el usuario cambia el
contenido de una celda y actualiza para que los cambios sean volcados en la base de datos
que alimenta el DataGridView.
Qu ocurre?. Que al actualizar el scroll sube a la parte de arriba, perdiendo de vista en la
pantalla el cambio efectuado.
La solucin es la siguiente:
int indiceFilaSelec = dataGridView1.CurrentRow.Index;
dataGridView1.FirstDisplayedScrollingRowIndex = indiceFilaSel
ec;

Tambin se puede obtener el ndice de la fila seleccionada


con dataGridView1.SelectedRows[0].Index;

Colocar un Ancho Fijo a una Columna de


un datagridview en visual C# 2008
Puede ser as :
private void FormartoGrilla()
{
dgvPersona.Columns[0].Width = 70;
dgvPersona.Columns[1].Width = 150;
}

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

martes, 1 de junio de 2010

[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#]
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
{
DataGridViewTextBoxEditingControl dText =
(DataGridViewTextBoxEditingControl)e.Control;

dText.KeyPress -= new KeyPressEventHandler(dText_KeyPress);


dText.KeyPress += new KeyPressEventHandler(dText_KeyPress);

}
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]

Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object,


ByVal e As DataGridViewEditingControlShowingEventArgs)
Dim columnIndex As Integer = dataGridView1.CurrentCell.ColumnIndex
If dataGridView1.Columns(columnIndex).Name = "Descripcion" Then
Dim dText As DataGridViewTextBoxEditingControl =
DirectCast(e.Control, DataGridViewTextBoxEditingControl)
RemoveHandler dText.KeyPress, AddressOf dText_KeyPress
AddHandler dText.KeyPress, AddressOf dText_KeyPress
End If
End Sub
Private Sub dText_KeyPress(ByVal sender As Object, ByVal e As
KeyPressEventArgs)

Dim columnIndex As Integer = dataGridView1.CurrentCell.ColumnIndex


If dataGridView1.Columns(columnIndex).Name = "Descripcion" Then
e.KeyChar = Char.ToUpper(e.KeyChar)
End If
End Sub

[C#]

[VB.NET]

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#]
DataGridViewTextBoxEditingControl dText = null;
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
int columnIndex = dataGridView1.CurrentCell.ColumnIndex;
if (dataGridView1.Columns[columnIndex].Name == "Descripcion")
{
dText = (DataGridViewTextBoxEditingControl)e.Control;
}

dText.KeyPress += new KeyPressEventHandler(dText_KeyPress);

}
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);
}

void dText_KeyPress(object sender, KeyPressEventArgs e)


{
e.KeyChar = char.ToUpper(e.KeyChar);
}
[VB.NET]
Private dText As DataGridViewTextBoxEditingControl = Nothing
Private Sub dataGridView1_EditingControlShowing(ByVal sender As Object,
ByVal e As DataGridViewEditingControlShowingEventArgs) Handles
dataGridView1.EditingControlShowing
Dim columnIndex As Integer = dataGridView1.CurrentCell.ColumnIndex
If dataGridView1.Columns(columnIndex).Name = "Descripcion" Then
dText = DirectCast(e.Control, DataGridViewTextBoxEditingControl)
AddHandler dText.KeyPress, AddressOf dText_KeyPress
End If
End Sub
Private Sub dataGridView1_CellEndEdit(ByVal sender As Object, ByVal e As
DataGridViewCellEventArgs) Handles dataGridView1.CellEndEdit
Dim columnIndex As Integer = dataGridView1.CurrentCell.ColumnIndex
If dataGridView1.Columns(columnIndex).Name = "Descripcion" Then
RemoveHandler dText.KeyPress, AddressOf dText_KeyPress
End If
End Sub
Private Sub dText_KeyPress(ByVal sender As Object, ByVal e As
KeyPressEventArgs)
e.KeyChar = Char.ToUpper(e.KeyChar)
End Sub

[C#]

[VB.NET]

Publicado por Leandro Tuttini en 10:02 4 comentarios:


Etiquetas: DataGridView

domingo, 2 de mayo de 2010

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.

private void frmSucursales_Load(object sender, EventArgs e)


{
SucursalesEntities sucursalesContext = new SucursalesEntities();
dgvScursales.AutoGenerateColumns=false;
dgvScursales.DataSource = sucursalesContext.Sucursales;
//
// Luego de bindear la grilla, cargo el contenido de cada fila
// en el combo de telefonos para cada sucursal
//
LoadGrillaComboBoxTelefonos();
}
private void LoadGrillaComboBoxTelefonos()
{

foreach (DataGridViewRow row in dgvScursales.Rows)


{
int idSucursal = Convert.ToInt32(row.Cells["IdSucursal"].Value);
DataGridViewComboBoxCell comboboxCell = row.Cells["Telefonos"] as
DataGridViewComboBoxCell;
SucursalesEntities sucursalesContext = new SucursalesEntities();
comboboxCell.DataSource = sucursalesContext.Telefonos.Where(x =>
x.IdSucursal == idSucursal);
comboboxCell.ValueMember = "Id";
comboboxCell.DisplayMember = "Numero";
}
}
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#]

[VB.NET]

Publicado por Leandro Tuttini en 20:41 25 comentarios:


Etiquetas: DataGridView, WinForm

jueves, 22 de abril de 2010

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.
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.

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 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
//

foreach (DataGridViewRow row in rowSelected)


{
dtoProductos.ProductosRow productoRow =
datos.Productos.NewProductosRow();
productoRow.Descripcion =
Convert.ToString(row.Cells["DescripcionSel"].Value);
productoRow.PrecioUnitario =
Convert.ToDecimal(row.Cells["PrecioUnitarioSel"].Value);
productoRow.UnidadMedida =
Convert.ToString(row.Cells["UnidadMedidaSel"].Value);
datos.Productos.Rows.Add(productoRow);
dgvSeleccion.Rows.Remove(row);
}
//
// Se binden los datos nuevamente, pero ahora con los nuevos
registros
// agregados del paso anterior
//
dgvProductos.AutoGenerateColumns = false;
dgvProductos.DataSource = datos;
dgvProductos.DataMember = "Productos";
}
}
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#]

[VB.NET]

Publicado por Leandro Tuttini en 8:36 116 comentarios:


Etiquetas: DataGridView

jueves, 15 de abril de 2010

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.
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.

private void dataGridView1_CellContentClick(object sender,


DataGridViewCellEventArgs e)
{
//
// Detecta si se ha seleccionado el header de la grilla
//
if (e.RowIndex == -1)
return;
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;
if (Convert.ToBoolean(cellSelecion.Value))
{
string mensaje = string.Format("Evento
CellContentClick.\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);
}
else
{
string mensaje = string.Format("Evento
CellContentClick.\n\nSe ha quitado la seleccion, \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);
}

}
}
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]

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.
private void dataGridView1_CellContentClick(object sender,
DataGridViewCellEventArgs e)
{
//
// Detecta si se ha seleccionado el header de la grilla
//
if (e.RowIndex == -1)
return;
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;
if (Convert.ToBoolean(cellSelecion.Value))
row.DefaultCellStyle.BackColor = Color.Green;
else
row.DefaultCellStyle.BackColor = Color.White;
}
}
private void dataGridView1_CurrentCellDirtyStateChanged(object sender,
EventArgs e)
{
if (dataGridView1.IsCurrentCellDirty)
{
dataGridView1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
}
Simplemente ante la deteccin de la seleccin del usuario se cambia el color de la fila usando el
DefaultCellStyle.BackColor.

[C#]

[VB.NET]

Publicado por Leandro Tuttini en 5:59 69 comentarios:


Etiquetas: DataGridView, WinForm

jueves, 1 de abril de 2010

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#]
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 ((!dataGridView1.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);
//
// Obtenemos la fila actual
//
DataGridViewRow row = dataGridView1.CurrentRow;
if (rbMostrarMensaje.Checked)
{
MessageBox.Show(string.Format("Se ha seleccionado, Cuenta:'{0}'
Descripcion:'{1}'",
row.Cells["cuenta"].Value,
row.Cells["descripcion"].Value));
}
else if (rbMostrarForm.Checked)
{
int cuenta = Convert.ToInt32(row.Cells["cuenta"].Value);
string desc = Convert.ToString(row.Cells["descripcion"].Value);

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,
' 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]

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#]
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,

' se abandonamos el procedimiento, llamando al metodo base


'
If (Not listView1.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
'
' Sino hay item seleccinado en la lista
' se abandonamos el procedimiento, llamando al metodo base
'
If listView1.SelectedItems.Count = 0 Then
Return MyBase.ProcessCmdKey(msg, keyData)
End If
'
' Obtenemos la fila actual
'
Dim item As ListViewItem = listView1.SelectedItems(0)
If rbMostrarMensaje.Checked Then
MessageBox.Show(String.Format("Se ha seleccionado,
Cuenta:'{0}' Descripcion:'{1}'", item.Text, item.SubItems(1).Text))
ElseIf rbMostrarForm.Checked Then
Dim cuenta As Integer = CInt(item.Text)
Dim desc As String = CStr(item.SubItems(1).Text)
Dim frm As New frmSeleccion(cuenta, desc)
frm.ShowDialog()
End If
Return True
End Function

[C#]

[VB.NET]

Publicado por Leandro Tuttini en 20:49 39 comentarios:


Etiquetas: DataGridView, WinForm

sbado, 20 de marzo de 2010

[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

private void dataGridView1_EditingControlShowing(object sender,


DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewComboBoxEditingControl dgvCombo = e.Control as
DataGridViewComboBoxEditingControl;
if (dgvCombo != null)
{
//
// se remueve el handler previo que pudiera tener asociado, a
causa ediciones previas de la celda
// evitando asi que se ejecuten varias veces el evento
//
dgvCombo.SelectedIndexChanged -= new
EventHandler(dvgCombo_SelectedIndexChanged);
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);
//
// se accede a la fila actual, para trabajr con otor de sus campos
// en este caso se marca el check si se cambia la seleccion
//
DataGridViewRow row = dataGridView1.CurrentRow;
DataGridViewCheckBoxCell cell = row.Cells["Seleccionado"] as
DataGridViewCheckBoxCell;
cell.Value = true;
}
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.
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (e.Control is ComboBox)
{
DataGridViewComboBoxEditingControl dgvCombo = e.Control as
DataGridViewComboBoxEditingControl;
//
// se remueve el handler previo que pudiera tener asociado, a
causa ediciones previas de la celda
// evitando asi que se ejecuten varias veces el evento
//
dgvCombo.SelectedIndexChanged -= new
EventHandler(dvgCombo_SelectedIndexChanged);
dgvCombo.SelectedIndexChanged += new
EventHandler(dvgCombo_SelectedIndexChanged);
}
}

[C#]

[VB.NET]

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.

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);
//

// se accede a la fila actual, para trabajr con otor de sus campos


// en este caso se marca el check si se cambia la seleccion
//
DataGridViewRow row = dataGridView1.CurrentRow;
DataGridViewCheckBoxCell cell = row.Cells["Seleccionado"] as
DataGridViewCheckBoxCell;
cell.Value = true;
}
private void dataGridView1_CellEndEdit(object sender,
DataGridViewCellEventArgs e)
{
if (dgvCombo != null)
dgvCombo.SelectedIndexChanged -= new
EventHandler(dvgCombo_SelectedIndexChanged);
}
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 evento CellEndEdit

[C#]

[VB.NET]

Publicado por Leandro Tuttini en 22:36 37 comentarios:


Etiquetas: DataGridView

lunes, 1 de marzo de 2010

[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.
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.

private void dataGridView1_CellValueChanged(object sender,


DataGridViewCellEventArgs e)
{
//
// Solo se trabaja ante los cambios en la columan de los checkbox
// y el ingreso de una canifad por el usuario
//
if (dataGridView1.Columns[e.ColumnIndex].Name == "Seleccion" ||
dataGridView1.Columns[e.ColumnIndex].Name == "Pedido")
{
decimal totalColumna = 0;
//
// Se recorre fila a fila para recalcular el total despues del
cambio

//
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]

Publicado por Leandro Tuttini en 17:19 45 comentarios:


Etiquetas: DataGridView

mircoles, 20 de enero de 2010

[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


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";
//
// bindeo los datos de los productos a la grilla
//
dataGridView1.AutoGenerateColumns = false;
dataGridView1.DataSource = ProductosDAL.GetAllProductos();
}

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;
}

private static MarcaEntity LoadMarca(IDataReader reader)


{
MarcaEntity marca = new MarcaEntity();
marca.IdMarca = Convert.ToInt32(reader["IdMarca"]);
marca.Descripcion = Convert.ToString(reader["Descripcion"]);
}

return marca;

public static List<ProductoEntity> GetAllProductos()


{

string sql = @"SELECT [IdProducto]


,[IdMarca]
,[Descripcion]
,[PrecioUnitario]
FROM Productos";
List<ProductoEntity> list = new List<ProductoEntity>();
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(LoadProducto(reader));
}
return list;
}
}
private static ProductoEntity LoadProducto(IDataReader reader)
{
ProductoEntity producto = new ProductoEntity();
producto.IdProducto = Convert.ToInt32(reader["IdProducto"]);
producto.IdMarca = Convert.ToInt32(reader["IdMarca"]);
producto.Descripcion = Convert.ToString(reader["Descripcion"]);
producto.PrecioUnitario =
Convert.ToDecimal(reader["PrecioUnitario"]);
return producto;
}

[C#]

[VB.NET]

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
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]

Publicado por Leandro Tuttini en 10:55 181 comentarios:


Etiquetas: C#, DataGridView, VB.NET

domingo, 3 de enero de 2010

[DataGridView] Pasaje de informacin entre grids


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.
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.

public partial class Form1 : Form, IAddItem


{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 formAdd = new Form2();
formAdd.Show(this);
}

#region IAddItem Members


public void AddNewItem(DataGridViewRow row)
{
string item = row.Cells["item"].Value.ToString();
string desc = row.Cells["Desc"].Value.ToString();
this.dataGridView1.Rows.Add(new []{ item, desc });
}
#endregion
}

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:
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]

Publicado por Leandro Tuttini en 20:20 47 comentarios:


Etiquetas: C#, DataGridView, WinForm

jueves, 10 de diciembre de 2009

[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.
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewTextBoxEditingControl dText =
(DataGridViewTextBoxEditingControl)e.Control;
dText.KeyDown -= new KeyEventHandler(dText_KeyDown);
dText.KeyDown += new KeyEventHandler(dText_KeyDown);
}
void dText_KeyDown(object sender, KeyEventArgs e)
{
int rowIndex =
((System.Windows.Forms.DataGridViewTextBoxEditingControl)
(sender)).EditingControlRowIndex;
if (e.Alt && e.KeyCode == Keys.D)
{
frmSeleccionarProducto form = new frmSeleccionarProducto();
form.ShowDialog();
Producto productoSeleccionado = form.ProductSelected;

DataGridViewRow row = dataGridView1.Rows[rowIndex];


row.Cells["IdProducto"].Value = productoSeleccionado.IdProducto;
row.Cells["Descripcion"].Value =
productoSeleccionado.Descripcion;
row.Cells["precio"].Value = productoSeleccionado.Precio;
}

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]

Publicado por Leandro Tuttini en 20:38 8 comentarios:


Etiquetas: C#, DataGridView, WinForm

[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

private void dataGridView1_CellFormatting(object sender,


DataGridViewCellFormattingEventArgs e)
{
DataGridViewColumn currentColumn =
dataGridView1.Columns[e.ColumnIndex];
if (currentColumn.Name == "Fracciona")
{
DataGridViewRow currentRow = dataGridView1.Rows[e.RowIndex];
DataRowView data = currentRow.DataBoundItem as DataRowView;
if (data == null)
return;
if(Convert.ToBoolean(data["fracc"]))
currentRow.Cells["tipoventa"].Value =
Convert.ToString(data["FORM_VENT"]);
else
currentRow.Cells["tipoventa"].Value =
Convert.ToString(data["PRESENTACI"]);
}
}
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
propiedad DataPropertyName 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
private DataTable GetDataTable()
{
DataTable dt = new DataTable();
dt.Columns.Add("fracc", typeof(bool));
dt.Columns.Add("PRESENTACI");
dt.Columns.Add("FORM_VENT");
DataRow row = dt.NewRow();
row["fracc"] = true;
row["PRESENTACI"] = "PRESENTACI 1";
row["FORM_VENT"] = "FORM_VENT 1";

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]

Publicado por Leandro Tuttini en 18:10 25 comentarios:


Etiquetas: C#, DataGridView

mircoles, 2 de diciembre de 2009

[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.

private void dataGridView1_CellEnter(object sender,


DataGridViewCellEventArgs e)
{
dataGridView1.BeginEdit(false);
}
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
DataGridViewTextBoxEditingControl dText =
(DataGridViewTextBoxEditingControl)e.Control;
dText.KeyUp -= new KeyEventHandler(text_KeyUp);
dText.KeyUp += new KeyEventHandler(text_KeyUp);
}
void text_KeyUp(object sender, KeyEventArgs e)
{
int rowIndex =
((System.Windows.Forms.DataGridViewTextBoxEditingControl)
(sender)).EditingControlRowIndex;
if (e.KeyCode == Keys.Enter)
{
int valueEntered = Convert.ToInt32(dataGridView1.Rows[rowIndex 1].Cells["cuenta"].Value);
dataGridView1.Rows[rowIndex - 1].Cells["descripcion"].Value =
this.Search(valueEntered);
}

}
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

private DataTable GetDataTable()


{
DataTable dt = new DataTable();
dt.Columns.Add("cuenta");
dt.Columns.Add("descripcion");
DataRow row = dt.NewRow();
row["cuenta"] = "1001";
row["descripcion"] = "cuenta 1001";
dt.Rows.Add(row);
row = dt.NewRow();
row["cuenta"] = "1002";
row["descripcion"] = "cuenta 1002";
dt.Rows.Add(row);
row = dt.NewRow();
row["cuenta"] = "1003";
row["descripcion"] = "cuenta 1003";
dt.Rows.Add(row);
return dt;
}
private string Search(int cuenta)
{
string descripcion = (from item in this.GetDataTable().AsEnumerable()
where Convert.ToInt32(item["cuenta"]) == cuenta
select
item["descripcion"].ToString()).FirstOrDefault<string>();
return descripcion;
}

[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.

Diseo del Formulario

Nota: Agregar un Label y en su propiedad Name colocar lblcodigo y en la


propiedad Text colocar el valor 1, esto nos permitir autogenerar el cdigo.

Ac les muestro el Cdigo:


using System;
using System.Collections.Generic;

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();
}

private void FrmListView_Load(object sender, EventArgs e)


{
listView1.Columns.Add("Cdigo", 70, HorizontalAlignment.Left);
listView1.Columns.Add("Apellidos", 150, HorizontalAlignment.Left);
listView1.Columns.Add("Nombre(s)", 150, HorizontalAlignment.Left);
listView1.Columns.Add("Edad", 50, HorizontalAlignment.Left);
listView1.Columns.Add("Telfono", 80, HorizontalAlignment.Left);
listView1.Columns.Add("Sexo", 90, HorizontalAlignment.Left);
listView1.View = View.Details;
}
private void Limpiar()
{
foreach (Control obj in this.groupBox1.Controls)
{
if (obj is TextBox)
{
obj.Text = "";
}
txtapellidos.Focus();
}
}
private void GeneraCodigo()
{
int c;
int nuevo;
string elemento;
c = listView1.Items.Count - 1;
elemento = listView1.Items[c].Text.ToString();
nuevo = Convert.ToInt16(elemento) + 1;
lblcodigo.Text = nuevo.ToString();
}
private void SoloLetras(object sender, KeyPressEventArgs e)
{
int keyascii = Convert.ToInt32(e.KeyChar);

if ((keyascii >= 65 && keyascii <= 90) ||


(keyascii >= 97 && keyascii <= 122) ||
(keyascii == 32) || (keyascii == 8))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}
private void SoloNumeros(object sender, KeyPressEventArgs e)
{
int keyascii = Convert.ToInt32(e.KeyChar);
if ((keyascii >= 48 && keyascii <= 57) || (keyascii == 8))
{
e.Handled = false;
}
else
{
e.Handled = true;
}
}
private void btneliminar_Click(object sender, EventArgs e)
{
int numindex = listView1.Items.Count - 1;

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();
}
}
}

Espero que sea de su utilidad Atte Shami....

Potrebbero piacerti anche