none
Cellformatting que no funciona bien RRS feed

  • Pregunta

  • Resulta que tengo un DataGridView que se llena de valores que levanto de una consulta. Ahora bien, traigo un campo que define si la mercadería que está listada tiene un estado: Vigente, o No Vigente.

    Hice un pequeño paso lógico que si el producto es vigente me colorea de verde la fila y de amarillo si es no vigente. Ahora bien, resulta que por las dimensiones del DGV y por los datos que se cargan en las columnas anteriores a la que está esta definición, me queda fuera de la visión en el DGV cuando se carga y el evento Cellformatting no funciona !!! como es posible esto ? 

    Esto lo confirmé ya que esa columna la puse al inicio de todas las columnas y sí funciona el cellformatting 


    • Cambiado Enrique M. Montejo sábado, 30 de agosto de 2014 10:48 Pregunta relacionada con controles de Windows Forms.
    viernes, 22 de agosto de 2014 14:38

Todas las respuestas

  • No repro. El formateo de la columna es on demand.

    Un form y un dgv

    Public Class Form1
    
        Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            DataGridView1.Columns.Add("c1", "AAA")
            DataGridView1.Columns.Add("c2", "BBB")
            DataGridView1.Columns.Add("c3", "CCC")
            DataGridView1.Columns.Add("c4", "DDD")
            DataGridView1.Columns.Add("total", "Total")
            DataGridView1.Columns("total").DefaultCellStyle.Format = "#,##0.00;(-#,##0.00)"
            DataGridView1.Columns("total").ValueType = GetType(Decimal)
            DataGridView1.Rows.Add(4)
            DataGridView1.Rows(0).Cells("total").Value = 100.32
            DataGridView1.Rows(1).Cells("total").Value = -84.21
            DataGridView1.Rows(2).Cells("total").Value = 310
            DataGridView1.Rows(3).Cells("total").Value = -153.98
        End Sub
    
        Private Sub DataGridView1_CellFormatting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            Dim dgv As DataGridView = CType(sender, DataGridView)
    
            If dgv.Columns("total").Index = e.ColumnIndex Then
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.ForeColor = If(CDec(e.Value) < 0, Color.Red, Color.Green)
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = If(CDec(e.Value) < 0, Color.Goldenrod, Color.Honeydew)
            End If
        End Sub
    End Class
    

    Muestra tus cartas.

    [W]

    viernes, 22 de agosto de 2014 15:28
  • Private Sub DataGridView2_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView2.CellFormatting
            If DataGridView2.Columns(e.ColumnIndex).Name = "COMVIG" Then
                Dim row As DataGridViewRow = DataGridView2.Rows(e.RowIndex)
                Dim cell As DataGridViewCell = DataGridView2.Rows(e.RowIndex).Cells("COMVIG")
    
                If CStr(cell.Value) = "0" Then
                    cell.Value = "NO"
                End If
    
                If CStr(cell.Value) = "1" Then
                    cell.Value = "SI"
                End If
            End If
    
            If DataGridView2.Columns(e.ColumnIndex).Name = "COMVIG" Then
                Dim row As DataGridViewRow = DataGridView2.Rows(e.RowIndex)
                Dim cell As DataGridViewCell = DataGridView2.Rows(e.RowIndex).Cells("COMVIG")
                If CStr(cell.Value) = "NO" Then
                    row.DefaultCellStyle.BackColor = Color.Beige
                End If
    
                If CStr(cell.Value) = "SI" Then
                    row.DefaultCellStyle.BackColor = Color.LightGreen
                End If
            End If
        End Sub

    este es mi codigo en el cellformatting

    fijate que si colocas en tu codigo lo siguiente en el cellformatting, reproduce lo que me pasa a mi:

    Dim row As DataGridViewRow = DataGridView1.Rows(e.RowIndex)
    row.DefaultCellStyle.BackColor = If(CDec(e.Value) < 0, Color.Red, Color.Green)
    row.DefaultCellStyle.BackColor = If(CDec(e.Value) < 0, Color.Goldenrod, Color.Honeydew)

    Si achicás el datagridview y te queda la columna TOTAL fuera del alcance visual del control, las celdas no las colorea... 

    • Editado Mnibor viernes, 22 de agosto de 2014 16:41
    viernes, 22 de agosto de 2014 16:24
  • Sí, espantoso.

    El punto es que el evento está diseñado para dar formato a una celda individual de manera dinámica (format-ing). O sea, para proveer un reemplazo del default cell style.

    Digo, no uses la propiedad DefaultCellStyle dentro del CellFormating.


    [W]

    viernes, 22 de agosto de 2014 17:17
  • y como coloreo toda la fila y no solamente una celda como en el caso que me enviaste ?
    viernes, 22 de agosto de 2014 17:45
  • No la condiciones a una columna. Si quitas el If el formato se aplicacrá a todas las columnas.

    [W]

    viernes, 22 de agosto de 2014 17:59
  • Si hago lo siguiente:

     Private Sub DataGridView1_CellFormatting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            Dim dgv As DataGridView = CType(sender, DataGridView)
    
            'If dgv.Columns("total").Index = e.ColumnIndex Then
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.ForeColor = If(CDec(e.Value) < 0, Color.Red, Color.Green)
                DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = If(CDec(e.Value) < 0, Color.Goldenrod, Color.Honeydew)
            'End If
        End Sub

    No funciona. No "pinta" toda la fila...

    viernes, 22 de agosto de 2014 18:04
  • Pero en tu programa sí funciona porque cell es la celda en la columna "COMVIG".

    ---

    Mi ejemplo

        Private Sub DataGridView1_CellFormatting(sender As System.Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView1.CellFormatting
            Dim dgv As DataGridView = CType(sender, DataGridView)
            Dim cell As DataGridViewCell = dgv.Rows(e.RowIndex).Cells("total")
    
            DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.ForeColor = If(CDec(cell.Value) < 0, Color.Red, Color.Green)
            DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Style.BackColor = If(CDec(cell.Value) < 0, Color.Goldenrod, Color.Honeydew)
        End Sub
    


    [W]


    • Editado [Walter] viernes, 22 de agosto de 2014 18:18
    viernes, 22 de agosto de 2014 18:08
  • No sé... sigue sin funcionar... no hace lo que quiero que haga... lo bueno del código que me proponés (el primero) es que achicando el DGV a un tamaño minimo por ejemplo de 245 x 245 las celdas SI me las formatea. Es decir, funciona. Lo mismo ocurre cuando lo maximizo a una medida de 900 x 245 por ejemplo. 

    Mi código también funciona, pero ocurre que si hago el DGV de 245 x 245 no funciona... lo hago de 900 x 245 y si funciona... todo depende si la columna COMVIG está visible en el control... 

    Pero el problema es que el código que me propones no me colorea toda la fila (inclusive aplicando tu ultimo comentario) Creo que si no recorro todas las columnas con algun FOR ... EACH jamas lo va a hacer... pero no se... voy a tener que buscar más información...

    viernes, 22 de agosto de 2014 18:38
  • Al valor de la celda lo consigues de manera explícita. No importa si está visible o no.

    Private Sub DataGridView2_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView2.CellFormatting
    	Dim row As DataGridViewRow = DataGridView2.Rows(e.RowIndex)
    	Dim cell As DataGridViewCell = DataGridView2.Rows(e.RowIndex).Cells("COMVIG")
    
    	If CStr(cell.Value) = "0" Then
    		cell.Value = "NO"
    	End If
    
    	If CStr(cell.Value) = "1" Then
    		cell.Value = "SI"
    	End If
    
    	If CStr(cell.Value) = "NO" Then
    		row.Cells(e.ColumnIndex).Style.BackColor = Color.Beige
    	End If
    
    	If CStr(cell.Value) = "SI" Then
    		row.Cells(e.ColumnIndex).Style.BackColor = Color.LightGreen
    	End If
    End Sub
    
    

    Private Sub DataGridView2_CellFormatting(sender As Object, e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles DataGridView2.CellFormatting
    	Dim row As DataGridViewRow = DataGridView2.Rows(e.RowIndex)
    	Dim cell As DataGridViewCell = DataGridView2.Rows(e.RowIndex).Cells("COMVIG")
    
    	If CStr(cell.Value) = "0" Then
    		cell.Value = "NO"
    		row.Cells(e.ColumnIndex).Style.BackColor = Color.Beige
    	End If
    
    	If CStr(cell.Value) = "1" Then
    		cell.Value = "SI"
    		row.Cells(e.ColumnIndex).Style.BackColor = Color.LightGreen
    	End If
    End Sub
    
    
    En el segundo caso el backcolor se asigna una sola vez a cada celda.

    [W]

    • Marcado como respuesta Enrique M. Montejo martes, 26 de agosto de 2014 14:47
    • Desmarcado como respuesta Mnibor martes, 26 de agosto de 2014 14:55
    viernes, 22 de agosto de 2014 20:36
  • NO ENTIENDO por qué Enrique Montejo da por respuesta a un código que no funciona y no soluciona el problema que planteo... 

    Si estan apurados en "marcar como resueltos" las consultas, sería bueno que avisen

    martes, 26 de agosto de 2014 14:57
  • Hola:
    En un Form con 1 DataGridView, coopia y pega el siguiente codigo.


    Imports System.Data.SqlClient

    Public Class Form1
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Me.dataGridView1.DataSource = ObtenerTabla()
        End Sub

        Private Sub dataGridView1_CellFormatting(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellFormattingEventArgs) Handles dataGridView1.CellFormatting
            ' si la celda corresponde a los ingresos anuales
            If Me.dataGridView1.Columns(e.ColumnIndex).Name = "Salario" Then
                ' y el valor cumple con cierta condición
                If IsDBNull(e.Value) = False Then
                    If CDec(e.Value) > 50000 Then
                        ' aplicar formato a la totalidad de la fila
                        Me.dataGridView1.Rows(e.RowIndex).DefaultCellStyle.BackColor = Color.Aquamarine
                    End If
                End If
            End If
        End Sub

        Private Function ObtenerTabla() As DataTable
            Try
                ' crear la sentencia sql para obtener las filas
                Dim sbSQL As New StringBuilder()
                sbSQL.Append("SELECT EmployeeID, ")
                sbSQL.Append("TitleOfCourtesy, FirstName, LastName, ")
                sbSQL.Append("BirthDate, Salario, Gender ")
                sbSQL.Append("FROM Employees ")
                sbSQL.Append("WHERE Title IS NOT NULL")
                ' conectar con la base de datos,
                Dim lsCadConexion As String = "Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"
                Using cnConexion As New SqlConnection(lsCadConexion)
                    ' ejecutar la consulta y devolver el resultado
                    Using cmdComando As New SqlCommand(sbSQL.ToString(), cnConexion)
                        Dim daAdaptador As New SqlDataAdapter(cmdComando)
                        Dim loDataTable As New DataTable()
                        daAdaptador.Fill(loDataTable)
                        Return loDataTable
                    End Using
                End Using
            Catch ex As Exception
                MessageBox.Show(ex.Message, "", MessageBoxButtons.OK, MessageBoxIcon.Information)
                Return Nothing
            End Try
        End Function
    End Class

    Un saludo desde Bilbo
    Carlos

    miércoles, 27 de agosto de 2014 8:26