IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Type de colonne d'un DatagridView hérité d'un UserControl


Sujet :

VB.NET

  1. #1
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut Type de colonne d'un DatagridView hérité d'un UserControl
    Bonjour,

    J'ai réussi, non sans mal à créer un contrôle Winforms StarRate qui représente un chiffre entier par des étoiles (représentation classique d'une notation de 1 à 5 par exemple).
    Je voudrais savoir si, une fois ceci réalisé, c'est compliqué de créer un type hérité de DataGridViewColumn que j'appellerais DataGridViewStarRateColumn, qui afficherait la valeur de type INTEGER, sous forme de StarRate.
    N'étant pas très à l'aise avec ces contrôles hérités d'autres contrôles, je viens vous demander une piste pour savoir par où commencer.
    J'ai trouvé ce lien qui explique comment transformer un champ texte contenant une date en DateTimePicker lorsqu'on cherche à le modifier mais je ne sais pas trop comment l'adapter. La question que je me pose souvent est : comment savoir quelles propriété du DataGridViewColumn il faut substituer.

    http://msdn.microsoft.com/fr-fr/libr...vs.110%29.aspx

    Apparemment, il faut aussi créer une classe héritée de DataGridViewCell, mais c'est pareil : que mettre dedans pour afficher un StarRate.

    Petite précision: les cellules de type StarRate n'ont pas vocation à être modifiée. J'ai l'impression que cela devrait faciliter le code.

  2. #2
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Hello Noftal,

    Décidément, t'en as des questions intéressantes .

    Justement ce matin, j'avais besoin d'avoir des boutons dans un datagridview qui puissent être désactivés.
    Heureusement, la MSDN avait déjà fait le boulot pour moi (voir code ci-dessous). J'imagine que cela devrait pouvoir te servir de base à la création de la classe DataGridViewStarRateColumn.
    Enfin, la colonne, c'est pas dur du tout. Le gros du boulot se trouve dans la classe DataGridViewStarRateCell que tu vas devoir créer.

    En fait, tout se passe dans l'event paint apparemment. Il faudra aussi, je pense, ajouter une propriété pour affecter la valeur (quoi qu'il y a déjà Value pour ça ).

    Tu partagerais ton contrôle StarRate ?? Je n'en ai à priori pas l'utilité pour le moment mais si jamais, je l'aurais sous le coude.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    Imports System.Windows.Forms.VisualStyles
     
    Public Class DataGridViewDisableButtonColumn
        Inherits DataGridViewButtonColumn
     
        Public Sub New()
            Me.CellTemplate = New DataGridViewDisableButtonCell()
        End Sub
    End Class
     
    Public Class DataGridViewDisableButtonCell
        Inherits DataGridViewButtonCell
     
        Private enabledValue As Boolean
        Public Property Enabled() As Boolean
            Get
                Return enabledValue
            End Get
            Set(ByVal value As Boolean)
                enabledValue = value
            End Set
        End Property
     
        ' Override the Clone method so that the Enabled property is copied. 
        Public Overrides Function Clone() As Object
            Dim Cell As DataGridViewDisableButtonCell = _
                CType(MyBase.Clone(), DataGridViewDisableButtonCell)
            Cell.Enabled = Me.Enabled
            Return Cell
        End Function
     
        ' By default, enable the button cell. 
        Public Sub New()
            Me.enabledValue = True
        End Sub
     
        Protected Overrides Sub Paint(ByVal graphics As Graphics, _
            ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
            ByVal rowIndex As Integer, _
            ByVal elementState As DataGridViewElementStates, _
            ByVal value As Object, ByVal formattedValue As Object, _
            ByVal errorText As String, _
            ByVal cellStyle As DataGridViewCellStyle, _
            ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
            ByVal paintParts As DataGridViewPaintParts)
     
            ' The button cell is disabled, so paint the border,   
            ' background, and disabled button for the cell. 
            If Not Me.enabledValue Then
     
                ' Draw the background of the cell, if specified. 
                If (paintParts And DataGridViewPaintParts.Background) = _
                    DataGridViewPaintParts.Background Then
     
                    Dim cellBackground As New SolidBrush(cellStyle.BackColor)
                    graphics.FillRectangle(cellBackground, cellBounds)
                    cellBackground.Dispose()
                End If
     
                ' Draw the cell borders, if specified. 
                If (paintParts And DataGridViewPaintParts.Border) = _
                    DataGridViewPaintParts.Border Then
     
                    PaintBorder(graphics, clipBounds, cellBounds, cellStyle, _
                        advancedBorderStyle)
                End If
     
                ' Calculate the area in which to draw the button. 
                Dim buttonArea As Rectangle = cellBounds
                Dim buttonAdjustment As Rectangle = _
                    Me.BorderWidths(advancedBorderStyle)
                buttonArea.X += buttonAdjustment.X
                buttonArea.Y += buttonAdjustment.Y
                buttonArea.Height -= buttonAdjustment.Height
                buttonArea.Width -= buttonAdjustment.Width
     
                ' Draw the disabled button.                
                ButtonRenderer.DrawButton(graphics, buttonArea, _
                    PushButtonState.Disabled)
     
                ' Draw the disabled button text.  
                If TypeOf Me.FormattedValue Is String Then
                    TextRenderer.DrawText(graphics, CStr(Me.FormattedValue), _
                        Me.DataGridView.Font, buttonArea, SystemColors.GrayText)
                End If
     
            Else
                ' The button cell is enabled, so let the base class  
                ' handle the painting. 
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, _
                    elementState, value, formattedValue, errorText, _
                    cellStyle, advancedBorderStyle, paintParts)
            End If
        End Sub
     
    End Class
    Kropernic

  3. #3
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Je vais regarder dans le détail ton message (et je t'en remercie). Mais sans attendre, je partage la source de mon StarRate.
    Je pense qu'il vaut mieux revenir à l'origine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    http://www.codeproject.com/Articles/5886/StarControl

  4. #4
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Re-salut Kropernic

    En m'inspirant du code de ma classe StarRate, j'ai pu reprendre ton code. Seul la procédure OnPaint est modifiée comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
      Protected Overrides Sub Paint(ByVal graphics As Graphics, _
            ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
            ByVal rowIndex As Integer, _
            ByVal elementState As DataGridViewElementStates, _
            ByVal value As Object, ByVal formattedValue As Object, _
            ByVal errorText As String, _
            ByVal cellStyle As DataGridViewCellStyle, _
            ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
            ByVal paintParts As DataGridViewPaintParts)
     
            'Set the scaling mode to high quality (makes teh stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = My.Resources.star_xxl 'une étoile
            Dim starswidth As Integer = 20
            Dim starsheight As Integer = 20
     
            starValue = value
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            For i = 1 To starValue
                graphics.DrawImage(filledtouse, New Rectangle(cellBounds.X + (i * starswidth) - starswidth, cellBounds.Y + 0, starswidth, starsheight))
            Next
     
     
        End Sub
    Ensuite j'ai créé une colonne "column1" en lui attribuant le type DataGridViewDisableButtonColumn et la propriété DataPropertyName = Rating du nom du champ de ma DataTable qui contient la valeur.
    Le pb que je rencontre est un défaut de rafraichissement à l'exécution, au premier affichage, et en scrollant le DataGridview pour faire défiler les lignes.

    Exemple par l'image (le nombre d'étoile affiché attendu est celle de la colonne Rating:
    Nom : Capture.PNG
Affichages : 682
Taille : 13,1 Ko

    Nom : capture2.PNG
Affichages : 552
Taille : 19,0 Ko

    As-tu une idée pour résoudre ce genre de pb (qui n'est pas nouveau). Avant que tu me répondes j'étais à peu près au même résultat en utilisant les procédures événementielles du form. Cela dit je préfère ta méthode) ?

    EDIT : Je n'ai pas réussi à répondre à la question précédente mais j'ai réussi à contourner le pb. Voici ma solution (et tu vas vite comprendre pourquoi je ne m'en satisfais pas) :
    1°/ Hériter plutôt de DataGridViewTextBoxColumn et DataGridViewTextBoxCell
    2°/ Dans la méthode Paint dont j'ai donné le code ci-dessus, rajouter un appel à la méthode Paint standard au début de la procédure, ce qui donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
        Protected Overrides Sub Paint(ByVal graphics As Graphics, _
            ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
            ByVal rowIndex As Integer, _
            ByVal elementState As DataGridViewElementStates, _
            ByVal value As Object, ByVal formattedValue As Object, _
            ByVal errorText As String, _
            ByVal cellStyle As DataGridViewCellStyle, _
            ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
            ByVal paintParts As DataGridViewPaintParts)
     
            MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts)
     
            'Set the scaling mode to high quality (makes teh stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = My.Resources.star_xxl_20 'une étoile
            Dim starswidth As Integer = 20
            Dim starsheight As Integer = 20
     
            starValue = value
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            For i = 1 To starValue
                graphics.DrawImageUnscaledAndClipped(filledtouse, New Rectangle(cellBounds.X + (i * starswidth) - starswidth, cellBounds.Y + 0, Math.Min(starswidth, cellBounds.Width - (i - 1) * starswidth - 1), starsheight))
            Next
     
     
        End Sub
    Au passage tu remarques que j'ai remplacé DrawImage par DrawImageUnscaledAndClipped et changé les arguments pour tronquer l'affichage des étoiles si la largeur de la colonne n'est pas suffisante. C'est du détail pour ce qui nous intéresse ici.

    3°/ Si je lance l'exécution, mes étoiles s'affichent bien, sans pb de rafraichissement, mais en surimpression de la valeur du champ Rating qui s'affiche comme si la cellule était de type textbox. Pour éviter cela, je n'ai pas trouvé mieux que de modifier ta Sub New comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Public Sub New()
            Me.Style.ForeColor = Color.White
        End Sub
    Pas très élégant, hein ? Bon le pb n'est pas tant que ça ne marche que si le fond de la cellule est blanc aussi. Ca peut se perfectionner pour que la ForeColor soit égale au BackColor de la cellule.
    J'y vois juste un intérêt, c'est que je peux manipuler ma cellule comme si c'était toujours un textbox contenant une valeur numérique ; par exemple pour trier la colonne, rechercher la valeur etc...

    Pour conclure, en fait, ce qui me chagrine le plus, c'est de faire appel à l'ensemble de la procédure Paint du DataGridViewTextBoxCell. C'est une façon de régler mon pb de rafraichissement. Mais du coup, c'est comme si j'écrivais une page entière de texte pour ensuite tout effacer sauf une ligne au milieu, au lieu d'écrire directement la ligne du milieu.
    Je suppose que la méthode orthodoxe consiste à ne reprendre de cette procédure que le code .NET qui règle la question du rafraichissement. Mais je ne sais pas comment on fait pour trouver le code du Framwork pour cette procédure. Quelqu'un sait-il ? Cela me permettrait de trouver la partie de code qu'il faut que je garde

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Salut
    Pourquoi tu ne prends pas une colonne de type DataGridViewImageColumn existant en standard et tu dessines dans chaque cellule le nombre d'étoile souhaitée ?

  6. #6
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Oui, à priori, je dériverai aussi une colonne de type image. D'ailleurs, j'imagine que ton StarControl fonctionne avec des images aussi.

    La dérivation de DataGridViewButtonCell était juste pour l'exemple. Pour donner une idée de la direction à prendre.

    En dérivant DataGridViewImageCell, je pense qu'il n'y aussi que l'event paint à surcharger. En plus bien sûr d'ajouter une propriété pour stocker la valeur.
    Kropernic

  7. #7
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Ca plante carrément avec cette solution. voici mon code complet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    Imports System.Windows.Forms.VisualStyles
    Imports System.ComponentModel
     
    Public Class DataGridViewStarRateColumn
        Inherits DataGridViewImageColumn
     
     
        Public Sub New()
            Me.CellTemplate = New DataGridViewStarRateCell()
        End Sub
    End Class
     
    Public Class DataGridViewStarRateCell
        Inherits DataGridViewImageCell
     
        Private _starwidth As Integer = 20
        Private _starheigth As Integer = 20
     
     
        ' Override the Clone method so that the Enabled property is copied. 
        Public Overrides Function Clone() As Object
            Dim Cell As DataGridViewStarRateCell = _
                CType(MyBase.Clone(), DataGridViewStarRateCell)
            Return Cell
        End Function
     
        Public Sub New()
     
        End Sub
     
     
        Protected Overrides Sub Paint(ByVal graphics As Graphics, _
            ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
            ByVal rowIndex As Integer, _
            ByVal elementState As DataGridViewElementStates, _
            ByVal value As Object, ByVal formattedValue As Object, _
            ByVal errorText As String, _
            ByVal cellStyle As DataGridViewCellStyle, _
            ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
            ByVal paintParts As DataGridViewPaintParts)
     
     
            'Set the scaling mode to high quality (makes teh stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = My.Resources.star_xxl_20 'une étoile
     
            starValue = value
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            For i = 1 To starValue
                graphics.DrawImageUnscaledAndClipped(filledtouse, New Rectangle(cellBounds.X + (i * _starwidth) - _starwidth, cellBounds.Y + 0, Math.Min(_starwidth, cellBounds.Width - (i - 1) * _starwidth - 1), _starheigth))
            Next
     
     
        End Sub
     
    End Class
    Le message d'erreur est joint :

    Apparemment, je n'ai pas besoin de redéfinir la propriété Value car elle est accessible dans la méthode Paint
    Images attachées Images attachées  

  8. #8
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 239
    Points
    4 239
    Par défaut
    Bin d'après le message de l'exception, tu essaies quelque part de convertir un long en image. Y a comme qui dirait une couille dans le pâté ^^.
    (pas d'IDE à la maison et j'me sens pas de regarder ton code dans notepad donc j'y jetterais un oeil lundi si personne ne l'a fait et si t'as pas trouvé la solution entre temps)
    Kropernic

  9. #9
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Je pense que ça vient du DataPropertyName de la colonne que j'avais laissé à "Rating" pour indiquer au DTG de récupérer la valeur Integer du champ Rating.
    En effet, si je réinitialise cette propriété, je n'ai plus de message d'erreur. Mais je n'affiche pas grand chose ce qui n'est normal car l'instruction starValue=value de mon message précédent ne donne rien.
    Du coup, en optant pour DataGridViewImageColumn, je déplace le pb : comment spécifier que la valeur de la cellule est celle de mon champ Rating ? Je ne suis pas sûr que la réponse à cette question soit plus simple que celle que j'ai posée avec l'option DataGridViewtextBoxColumn.

    EDIT : autrement dit, je ne suis pas certain que ma classe soit plus proche de DataGridViewImageColumn que de DataGridViewtextBoxColumn. Au moins avec cette dernière je récupère facilement la valeur.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Pour un Datagridview en mode non virtuel je passerai par l'événement CellFormatting du DGV, depuis cet événement tu récupères la valeur "Rating" en integer d'une colonne dédiée de type ...TextboxColumn qui la contient et que tu rends invisible. Tu construis ton image dans la sub de l'événement CellFormatting, ta colonne étant du type DataGridViewImageColumn.
    Pour un Datagridview en mode vituel tu passes pas l'événement CellValueNeeded.
    Comme évoqué précédemment, il ne me semble pas nécessaire de créer une colonne de type DataGridViewStarRateColumn.

    EDIT : en mode virtuel il est inutile de créer une colonne invisible, tu récupères directement la valeur dans ta source de données, a priori une datatable.

  11. #11
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Merci pour ta réponse.
    si tu compares ta suggestion à la situation précédente :
    http://www.developpez.net/forums/d14...l/#post7969975

    je ne trouve pas que ce soit plus léger : créer une colonne masquée etc... versus : lancer une procédure paint complète et masquer artificiellement la valeur en lui donnant une couleur égale au fond de la cellule.
    A choisir, je préfère encore la précédente.
    Mais je suis surpris que personne n'ait pu m'expliquer comment on trouve le code de la procédure Paint de base ou comment juste recoder ce dont on a besoin dans cette proc et compléter par ce qui est spécifique.
    Cela dit, mon message est assez récent. Laissons le temps au temps.

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par noftal Voir le message
    je ne trouve pas que ce soit plus léger
    Je n'ai pas dit que c'était plus léger mais cela me parait une solution simple et fiable. Jouer sur la couleur du texte c'est bidouiller, il suffit que le thème de Windows change, que tu décides d'appliquer des couleurs à tes lignes pour que ta solution ne fonctionne plus, sauf à réécrire du code pour t'assurer de la couleur de la ligne, pas terrible en terme de maintenance.
    Par ailleurs la colonne invisible n'est pas utile en mode virtuel (cf mon EDIT précédent). En mode standard tu as peut être un autre moyen pour récupérer la valeur du Rating directement dans ta source de données, dans tous les cas créer une colonne invisible ne sera pas perceptible sur les performances pour un tableau de plusieurs centaines de lignes.

    EDIT : l'exercice de créer une class DataGridViewStarRateColumn est intéressant, faut t-il que le résultat reste suffisamment propre pour l'utiliser.

  13. #13
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    Citation Envoyé par Zozodev Voir le message
    Jouer sur la couleur du texte c'est bidouiller, il suffit que le thème de Windows change, que tu décides d'appliquer des couleurs à tes lignes pour que ta solution ne fonctionne plus, sauf à réécrire du code pour t'assurer de la couleur de la ligne, pas terrible en terme de maintenance.
    Même avec ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        Public Sub New()
            Me.Style.ForeColor =  (New DataGridView).DefaultCellStyle.BackColor
       End Sub
    EDIT : non, ça n'est pas robuste. il faudrait vraiment que je récupère les propriétés du DataGridView parent de la colonne.
    J'ai pensé à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     Public Sub New()
            Dim d As DataGridView = Me.DataGridView
            Me.Style.ForeColor = d.AlternatingRowsDefaultCellStyle.BackColor
        End Sub
    Mais pour une raison que je ne pige pas, cela provoque un plantage.

    En tout cas la récupération des propriétés du DTG renvoient à un autre topic que j'ai créé et dont la solution résoudrait bien des pb :
    http://www.developpez.net/forums/d14...n-classe-mere/

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Récupérer la couleur d'une cellule n'est pas simpliste car il faut connaitre l'objet qui la porte. Cela peut être la ligne, la colonne ou la cellule. Donc récupérer la couleur de la ligne peut ne pas marcher systématiquement.
    La couleur par défaut de la ligne peut être Grise, si la couleur de la cellule a été définie à "Rouge", alors c'est le rouge et pas le gris que l'on verra. Donc pour être sûr, il faut tester dans l'ordre des héritages des objets, celui qui définit en dernier la couleur.
    Dans ton cas, tu peux bien sûr partir du principe que tu ne définiras jamais la couleur au niveau de la colonne ou de la cellule mais s'il te prend un jour l'envie de mettre plein de couleur il faudra probablement revenir sur ton code.

    Ce qui me gène dans l'option que tu prends c'est d'essayer de mettre une image dans un champ texte, sauf à exploiter un éventuel backgroundimage si ça existe, cela ne me semble pas sain. La nature du message d'erreur remontée par la cellule en est l'expression.
    Ce que tu veux afficher c'est une image, pas un texte, même si les caractéristiques de cette image dépendent d'un entier. Donc en terme d'affichage il me semble logique de travailler sur un type ...imageColumn, en héritage dans un nouvel objet ou directement comme je le propose.
    Si tu penses qu'une colonne masquée dégrade les performances, fais un test pour le confirmer sur plusieurs milliers de lignes, et si c'est rédhibitoire alors il faudra de toute façon migrer vers un DGV virtuel car je doute qu'une simple colonne masquée contenant un entier contribue de façon majeur à la dégradation de la performance lors de l'affichage de ton tableau.

    Enfin pour le tri, car il me semble que tu évoquais ce besoin dans l'un de tes messages, il suffit de router la demande utilisateur exprimer sur la colonne de type image (dont tu as défini le tri sur "Programmatic") vers la colonne invisible, ou dans le cas d'un DGV virtuel effectuer le tri sur la colonne de ta datable qui contient le "Rating".

  15. #15
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    L'idéal serait en effet de hériter de DTGImageColumn et de reprogrammer l'exploitation du champ DataPropertyname pour qu'il fonctionne comme pour un DTGTextBoxColumn. Ceci afin d'éviter de créer un champ masqué.

    Pour la petite histoire j'ai touvé la solution avec ma classe héritée de DTGtextboxcolumn pour éviter e voir la valeur numérique s'afficher. Le code est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     Public Sub New()
        End Sub
     
     
        Protected Overrides Sub Paint(ByVal graphics As Graphics, _
            ByVal clipBounds As Rectangle, ByVal cellBounds As Rectangle, _
            ByVal rowIndex As Integer, _
            ByVal elementState As DataGridViewElementStates, _
            ByVal value As Object, ByVal formattedValue As Object, _
            ByVal errorText As String, _
            ByVal cellStyle As DataGridViewCellStyle, _
            ByVal advancedBorderStyle As DataGridViewAdvancedBorderStyle, _
            ByVal paintParts As DataGridViewPaintParts)
     
            MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Nothing, errorText, cellStyle, advancedBorderStyle, paintParts)
     
            'Set the scaling mode to high quality (makes teh stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = My.Resources.star_xxl_20 'une étoile
     
            starValue = value
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            For i = 1 To starValue
                graphics.DrawImageUnscaledAndClipped(filledtouse, New Rectangle(cellBounds.X + (i * _starwidth) - _starwidth, cellBounds.Y + 0, Math.Min(_starwidth, cellBounds.Width - (i - 1) * _starwidth - 1), _starheigth))
            Next
     
     
        End Sub
    La nouveauté est à la ligne 15 : je passe 2 paramètres à Nothing.
    Du coup , ma Sub New est réduite à sa plus simple expression.

    EDIT : pour revenir à ton argument qui est de privilégier un DTGImageColumn plutôt qu'un DTGTextBoxColumn, j'aimerais bien quand même approfondir le raisonnement. Pourquoi serait-ce mieux ? A partir du moment où la classe DTGTextBoxCell contient en natif une propriété Paint qui contient tous les objets graphiques pour pouvoir modifier la cellule, où est le pb ?

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 25
    Points : 27
    Points
    27
    Par défaut
    Citation Envoyé par noftal Voir le message
    EDIT : pour revenir à ton argument qui est de privilégier un DTGImageColumn plutôt qu'un DTGTextBoxColumn, j'aimerais bien quand même approfondir le raisonnement. Pourquoi serait-ce mieux ? A partir du moment où la classe DTGTextBoxCell contient en natif une propriété Paint qui contient tous les objets graphiques pour pouvoir modifier la cellule, où est le pb ?
    Dès lors que tu arrives à tes fins ce n'est pas un problème !
    Simplement il me semble préférable d'hériter de l'objet qui est le plus proche de ce que je veux faire pour en récupérer ses différents événements, propriétés dédiées, cela doit limiter l'usage de code spécifique et facilité la maintenance.
    Par exemple je pense avec un textboxcolumn la cellule doit pourvoir récupérer le curseur de la souris, est ce souhaité/utile, à toi de voir, sinon mettre la colonne sur ReadOnly.

    Mais tous les chemins mènent à Rome , en utilisant l’événement Paint qui gère un graphic, tu t'assures d'être "au dessus" des particularités des différents objets, donc pourquoi pas...

  17. #17
    Membre actif
    Inscrit en
    Juillet 2013
    Messages
    761
    Détails du profil
    Informations forums :
    Inscription : Juillet 2013
    Messages : 761
    Points : 274
    Points
    274
    Par défaut
    OK.
    je vais tester ce que cela donne comme ça.
    Je clos le topic.
    Je rappelle que celui-ci est toujours ouvert pour perfectionner la classe et la rendre plus user friendly (et pourquoi pas la rendre diffusable) en rendant certains paramètres des icônes paramétrables depuis le designer. Si quelqu'un a de bonnes idées...

    Merci à tous en tous cas

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Modifier le type de colonne d'un datagridview
    Par biscot19 dans le forum Windows Forms
    Réponses: 2
    Dernier message: 23/06/2012, 18h55
  2. modifier le type de colonne d'un datagridView
    Par jihad dans le forum VB.NET
    Réponses: 1
    Dernier message: 20/12/2010, 23h47
  3. Changer le type de colonne d'un DataGridView lié
    Par David Fouejio dans le forum Windows Forms
    Réponses: 7
    Dernier message: 19/03/2010, 16h30
  4. [DataGridView] Changer type de colonne lors d'un databind
    Par garciajulien dans le forum Windows Forms
    Réponses: 0
    Dernier message: 24/02/2010, 14h26
  5. Changement dynamique du type de colonne dans un datagridview
    Par hotsizzle dans le forum Windows Forms
    Réponses: 1
    Dernier message: 17/03/2009, 14h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo