Creando la Clase IntegerGridColumn
Voy a crear un nuevo proyecto GridExtension del tipo Biblioteca de Clases.
Al proyecto le agregaré una referencia al ensamblado System.Windows.Forms de forma que tenga acceso a las clases del control DataGridView.
Dentro del proyecto voy a crear un nuevo archivo IntegerGridColumn.cs/IntegerGridColumn.vb en el que voy a definir dos clases. La clase IntegerGridColumn que hereda de DataGridViewColumn y la clase IntegerGridCell que hereda de DataGridViewTextBoxCell.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace GridExtension { public class IntegerGridColumn : DataGridViewColumn { } public class IntegerGridCell : DataGridViewTextBoxCell { } }
Imports System.Windows.Forms Public Class IntegerGridColumn Inherits DataGridViewColumn End Class Public Class IntegerGridCell Inherits DataGridViewTextBoxCell End Class
En la clase IntegerGridCell voy a sobreescribir la propiedad ValueType para especificar que el tipo de los valores de la celda es Int32, y el método InitializeEditingControl para añadir un controlador de evento al evento KeyPress del control de edición de la celda.
El controlador de este evento (el método IntegerGridCell_KeyPress) va a ser el responsable de controlar que los caracteres se correspondan con caracteres numéricos. En caso contrario establece la propiedad Handled del objeto KeyPressEventArgs a true para anular el tratamiento de la tecla pulsada.
public class IntegerGridCell : DataGridViewTextBoxCell { public IntegerGridCell() : base() { } public override Type ValueType { get { return typeof(Int32); } } public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle) { base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle); Control ctl = DataGridView.EditingControl; ctl.KeyPress += new KeyPressEventHandler(IntegerGridCell_KeyPress); } private void IntegerGridCell_KeyPress(object sender, KeyPressEventArgs e) { DataGridViewCell currentCell = ((IDataGridViewEditingControl)sender).EditingControlDataGridView.CurrentCell; if (currentCell is IntegerGridCell) e.Handled = !char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar); } }
Public Class IntegerGridCell Inherits DataGridViewTextBoxCell Public Sub New() MyBase.New() End Sub Public Overrides ReadOnly Property ValueType As Type Get Return GetType(Int32) End Get End Property Public Overrides Sub InitializeEditingControl(rowIndex As Integer, initialFormattedValue As Object, dataGridViewCellStyle As DataGridViewCellStyle) MyBase.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle) Dim ctl As Control = DataGridView.EditingControl AddHandler ctl.KeyPress, AddressOf IntegerGridCell_KeyPress End Sub Private Sub IntegerGridCell_KeyPress(sender As Object, e As KeyPressEventArgs) Dim currentCell As DataGridViewCell = CType(sender, IDataGridViewEditingControl).EditingControlDataGridView.CurrentCell If TypeOf currentCell Is IntegerGridCell Then e.Handled = Not Char.IsControl(e.KeyChar) AndAlso Not Char.IsDigit(e.KeyChar) End If End Sub End Class
En el constructor de la clase IntegerGridColumn voy a llamar al constructor de DataGridViewColumn pasándole una instancia de IntegerGridCell como plantilla de celda. Voy a sobreescribir también la propiedad CellTemplate para comprobar que la celda que se establece como plantilla es del tipo IntegerGridCell.
public class IntegerGridColumn : DataGridViewColumn { public IntegerGridColumn() : base(new IntegerGridCell()) { } public override DataGridViewCell CellTemplate { get { return base.CellTemplate; } set { if (value != null && !value.GetType().IsAssignableFrom(typeof(IntegerGridCell))) throw new InvalidCastException("Debe ser del tipo IntegerGridCell"); base.CellTemplate = value; } } }
Public Class IntegerGridColumn Inherits DataGridViewColumn Public Sub New() MyBase.New(New IntegerGridCell()) End Sub Public Overrides Property CellTemplate As DataGridViewCell Get Return MyBase.CellTemplate End Get Set(value As DataGridViewCell) If value IsNot Nothing AndAlso _ Not value.GetType().IsAssignableFrom(GetType(IntegerGridCell)) Then Throw New InvalidCastException("Debe ser del tipo IntegerGridCell") End If MyBase.CellTemplate = value End Set End Property End Class
Con esto ya estaría creado el nuevo tipo de columna. Para probarlo voy a añadir a la solución un nuevo proyecto GridTest del tipo Aplicación de Windows Forms.
Al proyecto GridTest le he añadido una referencia al proyecto GridExtension.
En el formulario que Visual Studio crea por defecto le he añadido un control DataGridView al que le he agregado dos columnas: una columna Texto del tipo DataGridViewTextBoxColumn y una columna Entero del tipo IntegerGridColumn.
Ahora ya podemos arrancar la aplicación para comprobar el funcionamiento del nuevo tipo de columna.
El código completo de este artículo, tanto en C# como en Visual Basic, está disponible en:
Códigos de muestra - Ejemplos MSDN
Esto esta muy bueno, y si se pudiera hacer que la entrada de datos sea decimal, es decir como en un facturador que se entra el número 15000 y automáticamente acomoda el número a 15.000,00 ?
ResponderEliminarHola Rodolfo,
EliminarPara aceptar y formatear números decimales lo que haría es añadir un control de edición (seguramente con un MaskedTextBox) al estilo del ejemplo que tengo en el blog para crear columnas para editar fechas:
DataGridView. Columna con editor de fechas
A ver si saco un rato y monto un ejemplo.
Un saludo
He tardado un poco pero ya hay disponible un ejemplo de columna numérica que permite especificar el número de dígitos decimales:
EliminarColumna para números con decimales
Espero que sea de utilidad.
Gracias Asier, Voy a estar esperando tu ejemplo. Ojala sea con Net 2
ResponderEliminarHola Asier:
ResponderEliminarLo primero es darte las gracias por los ejemplos que tienes, ya que son realmente muy buenos.
También estaría interesado en ver un ejemplo donde una columna del datagridview solamente aceptase números con dos decimales.
Un Saludo.
No eres el primero que me lo pide. A ver si este fin de semana puedo preparar un ejemplo.
EliminarHe tardado un poco pero ya hay disponible un ejemplo de columna numérica que permite especificar el número de dígitos decimales:
EliminarColumna para números con decimales
Espero que sea de utilidad.
Es muy bueno tu ejemplo, yo tengo un problema, lo que necesito que aparesca un boton en la celda activa, para hacer una busqueda!
ResponderEliminarHoja Jorge.
ResponderEliminarÚltimamente ando con poco tiempo para preparar ejemplos, pero me lo apunto. A ver si puedo sacar un rato un día de estos.
Para hacerlo puedes fijarte en otros dos artículos del blog:
En Control TextBox con Botón muestro como crear un control TextBox que tenga un botón incorporado.
Una vez que tienes el control se trataría de crear un DataGridViewColumn que utilice como editor este control. Algo parecido a lo que muestro en el artículo DataGridView. Columna con editor de fechas, en el que creo una columna que utiliza el control DateTimePicker como editor.
Espero que te ayude.
Hola Doc, muy bueno blog, tengo una consulta después de crear la clase y agregarlo en la referencia no me sale el tipo de dato IntegerGridCell en la lista de tipos de datos al agregar o modificar un campo del DataGridView, yo estoy usando el VisualStudio Comunity 2015 crees que haya algún problema con esto? ojo que todo ha terminado ok con la clase, gracias
ResponderEliminarLo que te debería aparecer es el tipo IntegerGridColumn entre los tipos de columna a seleccionar cuando añades una nueva columna en el DataGridView. Si no te aparece prueba a recompilar la solución o a cerrar y volver a abrir el formulario para que se refresquen las referencias.
Eliminar