Ir al contenido principal

Personalizar DataGridView (I) - Pintar área vacía

Personalizar DataGridView (II) - Bloquear columnas de solo lectura.
Personalizar DataGridView - Actualizaciones.
Personalizar DataGridView (II.1) - Bloquear columnas de solo lectura.
Personalizar DataGridView (III) - Cambiar Diseñador.

Bien, como lo dice el titulo vamos a personalizar el control DataGridView y lo haremos en varios artículos, en este lo que hare es pintar el área del control que queda vacía cuando tenemos un origen de datos con pocos registros, a esta área la llamare "Empty Area", así que en lugar de que se vea de esta manera.


haré que se vea de esta otra manera.


para esto crearemos nuestro propio control que herede de DataGridView al cual llamare MEPDataGridView, sobre escribiremos los métodos OnCellPainting y OnPaint del control, creare 5 métodos auxiliares "PaintColumnHeader", "PaintIndicatorHeader", "PaintRowIndicator", "PaintCell" y "PaintEmptyArea" y un Argumento "PaintingEventArgs" que hereda de EventArgs que sera pasado a algunos de los métodos auxiliares. 

[C#]
 
public class MEPDataGridView : DataGridView
{        
    
    public MEPDataGridView()        
    {            
        this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        this.SetStyle(ControlStyles.ResizeRedraw, true);
        this.DoubleBuffered = true;        
    }

}
 
[VB.NET]
 
Public Class MEPDataGridView    
    Inherits DataGridView    
 
    Public Sub New()        
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.ResizeRedraw, True)
        Me.DoubleBuffered = True    
    End Sub

End Class
 

como bien podemos observar en el constructor he activado el DoubleBuffer para reducir el parpadeo (flicker) al dibujar el control cuando este cambie de dimensiones, para mayor referencia ControlStyles.

desde este articulo dibujare los encabezados de las columnas para mantener uniformidad en los colores de estas ya que al tener habilitados los estilos visuales para la aplicación "Application.EnableVisualStyles", es dificil obtener los colores predeterminados con que se pintan los encabezados, y en este caso necesito hacerlo así para mantener uniformidad al pintar la columna indicador en el "Empty Area".

Ahora agregaremos una nueva propiedad al control para indicarle cuando queremos que se pinten las filas en el "Empty Area", ha esta propiedad la llamare "FillEmptyArea" cuyo tipo sera "Boolean" true/false, cuyo valor predeterminado sera "false".

[C#]
 
private bool vFillEmptyArea;    

[DefaultValue(false)]
public bool FillEmptyArea
{
    get
    {
        return this.vFillEmptyArea;
    }
    set
    {
        this.vFillEmptyArea = value;
        if (this.IsHandleCreated)
            this.Invalidate(true);
    }
}
 
[VB.NET]
 
Private vFillEmptyArea As Boolean

<DefaultValue(False)> _
Public Property FillEmptyArea() As Boolean
    Get
        Return Me.vFillEmptyArea
    End Get
    Set(ByVal value As Boolean)
        Me.vFillEmptyArea = value
        If Me.IsHandleCreated Then
            Me.Invalidate(True)
        End If
    End Set
End Property
 

Ademas hare visible la propiedad “AutoGenerateColumns” para poder cambiar esta desde las propiedades del control en tiempo de diseño.

[C#]
 
[Browsable(true), DefaultValue(true)]
public new virtual bool AutoGenerateColumns
{
    get
    {
        return vAutoGenerateColumns;
    }
    set
    {
        vAutoGenerateColumns = value;
        base.AutoGenerateColumns = value;
    }
}
 
[VB.NET]
 
<Browsable(True), DefaultValue(True)> _
Public Overloads Property AutoGenerateColumns() As Boolean
    Get
        Return Me.vAutoGenerateColumns
    End Get
    Set(ByVal value As Boolean)
        Me.vAutoGenerateColumns = value
        MyBase.AutoGenerateColumns = value
    End Set
End Property
 

Ahora sobre escribiremos el evento "OnCellPainting" del control para dibujar los encabezados de las columnas y dibujar el indicador de la fila de cada registro del origen de datos.

[C#]
 
protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
{
    base.OnCellPainting(e);
    if (e.RowIndex == -1 && e.ColumnIndex == -1)
    {
        // Método auxiliar para pintar el encabezado de la columna indicador.
        this.PaintIndicatorHeader(e);
    }
    else if (e.RowIndex == -1 && e.ColumnIndex > -1)
    {
        // Método auxiliar para pinta los encabezados de las columnas
        this.PaintColumnHeader(new PaintingEventArgs(e.Graphics, e.CellBounds, e.RowIndex, e.ColumnIndex));
        e.PaintContent(e.ClipBounds);
        e.Handled = true;
     }
     else if (e.ColumnIndex == -1)
     {
        // Método auxiliar para pinta la columna indicador.
        this.PaintRowIndicator(new PaintingEventArgs(e.Graphics, e.CellBounds, e.RowIndex, e.ColumnIndex));
        e.PaintContent(e.ClipBounds);
        e.Handled = true;
     }
}
 
[VB.NET]
 
Protected Overrides Sub OnCellPainting(ByVal e As DataGridViewCellPaintingEventArgs)
    MyBase.OnCellPainting(e)

    If e.RowIndex = -1 And e.ColumnIndex = -1 Then
        ' Método auxiliar para pintar el encabezado de la columna indicador.
        Me.PaintIndicatorHeader(e)
    ElseIf e.RowIndex = -1 And e.ColumnIndex > -1 Then
        ' Método auxiliar para pinta los encabezados de las columnas
        Me.PaintColumnHeader(New PaintingEventArgs(e.Graphics, e.CellBounds, e.RowIndex, e.ColumnIndex))
        e.PaintContent(e.ClipBounds)
        e.Handled = True
    ElseIf e.ColumnIndex = -1 Then
        ' Método auxiliar para pinta la columna indicador.
        Me.PaintRowIndicator(New PaintingEventArgs(e.Graphics, e.CellBounds, e.RowIndex, e.ColumnIndex))
        e.PaintContent(e.ClipBounds)
        e.Handled = True
    End If

End Sub
 
Luego sobre escribimos el evento "OnPaint" para dibujar las filas o lineas para llenar el "Empty Area"

[C#]
 
protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);
    if (this.FillEmptyArea)
        // Método auxiliar para pintar el área vacía
        this.PaintEmptyArea(e);
}
 
[VB.NET]
 
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)
    If Me.FillEmptyArea Then _
        Me.PaintEmptyArea(e) ' Método auxiliar para pintar el área vacía
End Sub
 


y aquí les dejos los proyectos para que los descarguen.

Código fuente [C#]
Código fuente [VB.NET]


En el próximo artículo veremos como evitar que el usuario pueda colocarse sobre las columnas cuya propiedad "ReadOnly" este establecida en "true".


Espero que sea de utilidad este artículo y no olviden dejar sus comentarios.

Salu2,

Comentarios

Publicar un comentario

Entradas populares de este blog

NetBarControl

Actualización. NetBarControl - Description Item Style ( New ) NetBarControl ( Outlook Bar ) es uno de los controles que muchas veces buscamos para usar en nuestras aplicaciones, pero siempre encontramos en internet versiones pagables y tal vez no contamos con el presupuesto esperado como para comprar uno y las versiones gratis que se logran encontrar, pues como son gratis no implementan en su totalidad la funcionalidad que esperamos encontrar en un control de este tipo. Antes de comenzar a escribir este control dedique tiempo en buscar uno por internet que tuviera toda la funcionalidad o por lo menos una interfaz disponible en modo de diseño, pero, no logre encontrar uno, así que me propuse crearlo como a mí me gustaría que funcionara uno gratis y al final llegue a la conclusión de ¿Porque no hay uno completo, gratis y que incluya el código fuente? y la respuesta es: No es fácil , pero tampoco es cosa de otro mundo. Con esto no digo que otro programador no lo pueda hacer ...

TextBox con Icon/Imagen

Bien, continuando con este articulo: TextBox con borde personalizado , ahora le dare la funcionalidad de poder mostrar un icono o imagen dentro del Control TextBox. Existen dos maneras de hacer esto: Pintar el icono/imagen dentro del control o Pintar el icono/imagen dentro del Non-Client Area del control. Pintar el icono/imagen dentro del control. Antes de escribir el código decidi googlear un poco, para ver si alguien más ya habia tenido la misma idea de usar el mensaje EM_SETMARGINS para dejar el espacio necesario para pintar el icono o imagen ya sea a la derecha o izquierda y me he encontrado con este articulo. Adding an Icon or Control to a TextBox or ComboBox . Pintar el icono/imagen de ntro del Non-Client Area del control. Us ando el Non- Client Area no encontre resultados googleando, así que es la forma que usar e para dib ujar un icono o imagen dentro de un control TextBox. En el control TextEditor que escrib í, utilizo esta manera para pintar el icono...

TextBox con Borde Personalizado

Bien, retomando nuevamente mi blog, luego de tanto tiempo ausente, veremos como personalizar el borde del control TextBox con un color diferente. hace poco vi en los foros de MSDN, en el foro de VB.Net esta pregunta, ¿ Cómo puedo cambiar el color del borde de un control TextBox ?, anteriormente también se hizo la misma pregunta en este mismo foro donde yo respondí como hacerlo VB2010 4.0 - Como crear un textbox personalizado . no hay manera fácil de personalizar un control, generalmente se tiene que sobre escribir el evento WndProc para escuchar los mensajes de window y reemplazar la funcionalidad de estos según sea la necesidad o el control. bien, para cambiar el color del borde del control TextBox sin mucha funcionalidad, se debe de escuchar y reemplazar el funcionamiento de los mensajes WM_PAINT y WM_NCPAINT . ¿ Porque WM_PAINT ?, porque cuando cambiamos la propiedad BorderStyle de este control a FixedSingle, quien pinta el borde es el men...