A raíz de la publicación del artículo
DataGridView. Columna que acepta sólo números. un par de lectores del blog me cuestionaron sobre la forma de modificar el ejemplo para añadir la posibilidad de introducir números decimales.
Con el objetivo de responder a esta duda vamos a ver cómo podemos definir una columna a la que le podamos indicar no sólo el número de decimales a mostrar, si no también el separador decimal a utilizar a la hora de mostrar los valores.
Como en el ejemplo de la columna para números enteros voy a crear dos nuevas clases: una clase
NumericGridColumn para definir la columna y que heredará de
DataGridViewColumn, y otra clase
NumericGridCell para la celda y que heredará de
DataGridViewTextBoxCell.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Forms;
namespace GridExtension
{
public class NumericGridColumn : DataGridViewColumn
{
}
public class NumericGridCell: DataGridViewTextBoxCell
{
}
}
Imports System.ComponentModel
Imports System.Globalization
Imports System.Windows.Forms
Public Class NumericGridColumn
Inherits DataGridViewColumn
End Class
Public Class NumericGridCell
Inherits DataGridViewTextBoxCell
End Class
En primer lugar voy a crear dos nuevas propiedades en la clase
NumericGridColumn: una propiedad
DecimalSeparator que permitirá definir el carácter a utilizar como separador decimal, y una propiedad
DecimalDigits que indicará el número de decimales permitido.
Crearé también una tercera propiedad
NumberFormat para uso interno que devolverá el objeto
NumberFormatInfo a utilizar para formatear los números de las celdas. Si no se han indicado valores para las propiedades
DecimalSeparator y
DecimalDigits la propiedad
NumberFormat utilizará los valores definidos para la cultura actual.
public class NumericGridColumn : DataGridViewColumn
{
private NumberFormatInfo _numberFormat;
private string _decimalSeparator;
private int _decimalDigits = -1;
[Category("Appearance")]
public string DecimalSeparator {
get {
if (string.IsNullOrEmpty(_decimalSeparator))
return CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator;
else
return _decimalSeparator;
}
set
{
if (value.Length != 1)
throw new ArgumentException("El separador decimal debe ser un único caracter");
_decimalSeparator = value;
}
}
[Category("Appearance")]
public int DecimalDigits {
get
{
if (_decimalDigits < 0)
return CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalDigits;
else
return _decimalDigits;
}
set { _decimalDigits = value; }
}
internal NumberFormatInfo NumberFormat
{
get
{
if (_numberFormat == null)
_numberFormat = new NumberFormatInfo();
_numberFormat.NumberDecimalSeparator = DecimalSeparator;
_numberFormat.NumberDecimalDigits = DecimalDigits;
return _numberFormat;
}
}
}
Public Class NumericGridColumn
Inherits DataGridViewColumn
Private _numberFormat As NumberFormatInfo
Private _decimalSeparator As String
Private _decimalDigits As Integer
<Category("Appearance")>
Public Property DecimalSeparator As String
Get
If String.IsNullOrEmpty(_decimalSeparator) Then
Return CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator
Else
Return _decimalSeparator
End If
End Get
Set(ByVal value As String)
If value.Length <> 1 Then
Throw New ArgumentException("El separador decimal debe ser un único caracter")
End If
_decimalSeparator = value
End Set
End Property
<Category("Appearance")>
Public Property DecimalDigits As Integer
Get
If _decimalDigits < 0 Then
Return CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalDigits
Else
Return _decimalDigits
End If
End Get
Set(ByVal value As Integer)
_decimalDigits = value
End Set
End Property
Friend ReadOnly Property NumberFormat As NumberFormatInfo
Get
If _numberFormat Is Nothing Then _numberFormat = New NumberFormatInfo()
_numberFormat.NumberDecimalSeparator = DecimalSeparator
_numberFormat.NumberDecimalDigits = DecimalDigits
Return _numberFormat
End Get
End Property
End Class
Para completar el código de la columna en el constructor de la clase
NumericGridColumn voy a llamar al constructor de
DataGridViewColumn pasándole una instancia de
NumericGridCell como plantilla de celda. Voy a sobrescribir también la propiedad
CellTemplate para comprobar que la celda que se establece como plantilla es del tipo
NumericGridCell.
Por último sobrescribiré el método Clone para que se pasen los valores de las propiedades DecimalSeparator y DecimalDigits cuando se cree una columna clonando una ya existente.
public NumericGridColumn():base (new NumericGridCell()) { }
public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
if (value != null &&
!value.GetType().IsAssignableFrom(typeof(NumericGridCell)))
throw new InvalidCastException("Debe especificar una instancia de NumericGridCell");
base.CellTemplate = value;
}
}
public override object Clone()
{
NumericGridColumn newColumn = (NumericGridColumn)base.Clone();
newColumn.DecimalSeparator = DecimalSeparator;
newColumn.DecimalDigits = DecimalDigits;
return newColumn;
}
Public Sub New()
MyBase.New(New NumericGridCell())
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(NumericGridCell)) Then
Throw New InvalidCastException("Debe especificar una instancia de NumericGridCell")
End If
MyBase.CellTemplate = value
End Set
End Property
Public Overrides Function Clone() As Object
Dim newColumn As NumericGridColumn = MyBase.Clone()
newColumn.DecimalSeparator = DecimalSeparator
newColumn.DecimalDigits = DecimalDigits
Return newColumn
End Function
Artículo siguiente:
Windows Forms. DataGridView. Columna para números con decimales (y II)
Gracias Asiel, pero parece que falta la clase NumericGridCell, ya que no hace nada el eontrol, hace exactamente lo que hace la columna Integer.Es decir, no da el formato de números con puntos y decimales
ResponderEliminarLo puedes subir ?
Es urgente
Si quieres lo puedes enciar a mi email tambien.
Gracias