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 :

Classe : récupérer une propriété d'une autre classe qui est liée mais qui n'est pas une classe mère


Sujet :

VB.NET

  1. #21
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Points : 5 100
    Points
    5 100
    Par défaut
    Citation Envoyé par noftal Voir le message
    Ce que je comprends :
    - Les propriétés apparaissant dans le designer sont celles de la classe DataGridViewStarRateColumn
    - La propriété clone était correctement codée, c'est la façon de gérer les propriétés qui semble avoir posé pb dans la mémorisation des propriétés dans le designer: voir les 2 points suivants
    - Le Get de la propriété StarWidth de DataGridViewStarRateColumn va chercher sa valeur dans la propriété équivalente de DataGridViewStarRateCell (et non le contraire)
    Oui, je ne cherchais pas au bon endroit.
    Citation Envoyé par noftal Voir le message
    - Le Set de la propriété StarWidth de DataGridViewStarRateColumn met à jour la propriété équivalente de DataGridViewStarRateCell pour toutes les cellules de la colonne
    Oui, mais met à jour les toutes les cellules dans un seul cas : quand on modifie par code les propriétés (dans notre cas starheight, starwidth et StarAlignment) d'un datagridview qui contient des lignes. (fallait y penser) Sinon en création (code ou designer) l'affectation à la propriété suffit pour mettre en forme. (c'était une petite précision).
    Ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
            DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarWidth = 45
            DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarHeight = 45
            DataGridView1.Refresh()
    Sinon, je me permet de te proposer quelques suggestions

    Simplifier les 2 lignes en commentaires par l'autre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                    'Dim rowCount As Integer = dataGridViewRows.Count
                    'For rowIndex As Integer = 0 To rowCount - 1
                    For rowIndex As Integer = 0 To dataGridViewRows.Count - 1
    Voire même l'ensemble de cette façon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
            Set(ByVal value As Integer)
                DirectCast(CellTemplate, DataGridViewStarRateCell).StarWidth = value
                If Me.DataGridView IsNot Nothing Then
                    Dim cell As DataGridViewStarRateCell 
                    For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                        cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                        If cell IsNot Nothing Then cell.StarWidth = value
                    Next
                End If
            End Set
    Je trouve l'ensemble plus lisible, mais cela n'engage que moi.

    Dans paint de typer les calculs pour éviter les conversions implicite :
    srcRectWidth = CInt(width / _starwidth * destRectWidth),
    srcRectHeight = CInt(height * Math.Min(cellBounds.Height / _starheight, 1)),
    et aussi starValue = CInt(value).
    idem pour les calculs dans le case (le plus simple tu mets sur option strict on)

    Pour la ressource défini la en variable, et dans paint
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public Class DataGridViewStarRateCell
        Inherits DataGridViewTextBoxCell
     
        Const KMinValue As Integer = 10 ' ou 5
        Private img As Image = My.Resources.star_xxl 'une étoile
     
    '...
    ' dans paint
            Dim filledToUse As Image = img
    tu pourras même en faire une propriété.

    Pour finir
    Contrôler la valeur reçue pour starheight et starwidth (voir constante définie au dessus)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Set(ByVal value As Integer)
                If value < KMinValue Then _starwidth = KMinValue Else _starwidth = value
            End Set
    ou tout du moins interdire le 0 (zéro) pour éviter la division (par 0) dans paint

    Mais bon, ce ne sont que quelques idées, tu en fais ce que tu veux

    En tout cas bon boulot.
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  2. #22
    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
    Oui, mais met à jour les toutes les cellules dans un seul cas : quand on modifie par code les propriétés (dans notre cas starheight, starwidth et StarAlignment) d'un datagridview qui contient des lignes. (fallait y penser) Sinon en création (code ou designer) l'affectation à la propriété suffit pour mettre en forme. (c'était une petite précision).
    Ex :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarWidth = 45
            DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarHeight = 45
            DataGridView1.Refresh()
    Sinon, je me permet de te proposer quelques suggestions
    Je n'ai pas trop compris ta suggestion ? Est-ce que le code modificatif que tu proposes ensuite en tient compte ?
    J'ai effectivement remarqué qu'il faut faire un DataGridView1.Refresh() dès lors que je modifie les propriétés par le code. Y a-t-il un moyen de s'en affranchir ?

    Dans ce code modificatif, tu penses inutile de vérifier que la valeur de la propriété précédente était différente (If M.StarWidth <> value...) ?

    sinon, je te remercie pour tes précieuses suggestions, dont j'ai tenu compte.

    J'envisageais justement de créer une propriété pour l'image sous-jacente. Mais pour l'instant j'essaye de faire en sorte que le double click sur la bordure de la colonne du DTG provoque l'adaptation de la largeur au nombre max d'étoiles contenu dans la colonne. Ca n'a pas l'air simple cette histoire car il faut travailler sur une routine (que je n'ai pas encore identifié) de la classe DataGridview il me semble. Si tu as des suggestions, je suis preneur.

    Je redonne mon code mis à jour car j'ai rajouté un peu de code pour mettre des points de suspension en fin de cellule lorsque la taille n'est pas suffisante (ça c'est pas trop compliqué) :

    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
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    Imports System.Drawing
    Imports System.Windows.Forms
    Imports System.Windows.Forms.VisualStyles
    Imports System.ComponentModel
     
     
    Public Class DataGridViewStarRateColumn
        Inherits DataGridViewTextBoxColumn
     
        Public Sub New()
            Me.CellTemplate = New DataGridViewStarRateCell()
     
        End Sub
     
        <Category("Design")>
     <Description("Largeur de l'étoile")>
        Public Property StarWidth() As Integer
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarWidth
            End Get
     
            Set(ByVal value As Integer)
                If Me.StarWidth <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarWidth = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell 
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarWidth = value
                        Next
                    End If
                End If
            End Set
        End Property
     
        <Category("Design")>
    <Description("Hauteur de l'étoile")>
        Public Property StarHeight() As Integer
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarHeight
            End Get
            Set(value As Integer)
                If Me.StarHeight <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarHeight = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell 
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarHeight = value
                        Next
                    End If
                End If
            End Set
        End Property
     
        <Category("Design")>
    <Description("Alignement des étoiles dans la cellule")>
            Public Property StarAlignment() As DataGridViewContentAlignment
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarAlignment
            End Get
            Set(value As DataGridViewContentAlignment)
                If Me.StarAlignment <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarAlignment = value
                    If Me.DataGridView IsNot Nothing Then
                         Dim cell As DataGridViewStarRateCell 
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarHeight = value
                        Next
                    End If
                End If
            End Set
        End Property
     
     
        'Public Overrides Function GetPreferredWidth(autoSizeColumnMode As System.Windows.Forms.DataGridViewAutoSizeColumnMode, fixedHeight As Boolean) As Integer
        '    Return MyBase.GetPreferredWidth(autoSizeColumnMode, fixedHeight)
        'End Function
    End Class
     
     
     
    Public Class DataGridViewStarRateCell
        Inherits DataGridViewTextBoxCell
     
        Private _starwidth As Integer = 20
        Private _starheight As Integer = 20
        Private _staralignment As DataGridViewContentAlignment = DataGridViewContentAlignment.TopLeft
        Private _image As Image = My.Resources.star_xxl 'une étoile
        Const KminValue As Integer = 5
     
     
        Public Property StarWidth() As Integer
            Get
                Return _starwidth
            End Get
            Set(ByVal value As Integer)
                If value < KminValue Then _starwidth = KminValue Else _starwidth = value
            End Set
        End Property
     
     
        Public Property StarHeight() As Integer
            Get
                Return _starheight
            End Get
            Set(ByVal value As Integer)
                If value < KminValue Then _starheight = KminValue Else _starheight = value
            End Set
        End Property
     
     
        Public Property StarAlignment() As DataGridViewContentAlignment
            Get
                Return _staralignment
            End Get
            Set(ByVal value As DataGridViewContentAlignment)
                _staralignment = value
            End Set
        End Property
     
        Public Overrides Function Clone() As Object
            Dim Cell As DataGridViewStarRateCell = DirectCast(MyBase.Clone(), DataGridViewStarRateCell)
            Cell.StarWidth = Me.StarWidth
            Cell.StarHeight = Me.StarHeight
            Cell.StarAlignment = Me.StarAlignment
            Return Cell
        End Function
     
     
        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 the stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
     
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            ' le dessin est limité aux dimensions de la cellule
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = _image
            Dim height As Integer = filledtouse.Height
            Dim width As Integer = filledtouse.Width
            Dim destRectX, destRectY, destRectWidth, destRectHeight As Integer
            Dim srcRectWidth, srcRectHeight As Integer
            Dim destRect, srcRect As Rectangle
            Dim oAlignment As DataGridViewContentAlignment
            Dim sTronq As String = "..."
            Dim sTronqSize As SizeF = graphics.MeasureString(sTronq, cellStyle.Font)
            Dim iTronq As Single
            starValue = CInt(value)
            ' réglage alignement des étoiles dans la cellule
            Dim offsetX, offsetY As Integer
            Select Case _staralignment
                Case DataGridViewContentAlignment.BottomCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.BottomLeft
                    offsetX = 0 'left
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.BottomRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.MiddleCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.MiddleLeft
                    offsetX = 0 'left
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.MiddleRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.TopCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
                Case DataGridViewContentAlignment.TopLeft, DataGridViewContentAlignment.NotSet
                    offsetX = 0 'left
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
                Case DataGridViewContentAlignment.TopRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
            End Select
     
            If _starwidth * starValue > cellBounds.Width Then ' La taille de la cellule est insuffisante pour tout afficher
                cellStyle.Alignment = oAlignment
                iTronq = sTronqSize.Width
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, sTronq, sTronq, errorText, cellStyle, advancedBorderStyle, paintParts)
            Else
                iTronq = 0
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Nothing, errorText, cellStyle, advancedBorderStyle, paintParts)
            End If
     
     
            For i = 1 To starValue
                destRectX = cellBounds.X + offsetX + (i - 1) * _starwidth
                destRectY = cellBounds.Y + offsetY
                destRectWidth = Math.Min(_starwidth, cellBounds.Width - (i - 1) * _starwidth - CInt(iTronq)) - 1
                destRectHeight = Math.Min(cellBounds.Height, _starheight) - 1
                srcRectWidth = CInt(width / _starwidth * destRectWidth)
                srcRectHeight = CInt(height * Math.Min(cellBounds.Height / _starheight, 1))
                destRect = New Rectangle(destRectX, destRectY, destRectWidth, destRectHeight)
                srcRect = New Rectangle(0, 0, srcRectWidth, srcRectHeight)
                graphics.DrawImage(filledtouse, destRect, srcRect, GraphicsUnit.Pixel)
            Next
     
     
        End Sub
     
    End Class

  3. #23
    Modérateur

    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 722
    Points : 5 100
    Points
    5 100
    Par défaut
    Citation Envoyé par noftal Voir le message
    Citation Envoyé par rv26t Voir le message
    Oui, mais met à jour les toutes les cellules dans un seul cas : quand on modifie par code les propriétés (dans notre cas starheight, starwidth et StarAlignment) d'un datagridview qui contient des lignes. (fallait y penser) Sinon en création (code ou designer) l'affectation à la propriété suffit pour mettre en forme. (c'était une petite précision).
    Ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click ' j'aurai du mettre ainsi
            DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarWidth = 45
            DirectCast(DataGridView1.Columns("newColstar"), DataGridViewStarRateColumn).StarHeight = 45
            DataGridView1.Refresh()
    Je n'ai pas trop compris ta suggestion ? Est-ce que le code modificatif que tu proposes ensuite en tient compte ?
    J'ai effectivement remarqué qu'il faut faire un DataGridView1.Refresh() dès lors que je modifie les propriétés par le code. Y a-t-il un moyen de s'en affranchir ?
    Non, ce n'est pas une suggestion de modif, c'est une explication fonctionnelle. J'aurai du mettre le "boutonClic"
    C'est un exemple lorsque tu utilises le UserControl dans le code. Avec ce code la boucle de parcours des cellules du UserControle sera exécutée. (pour finir de préciser, en création de colonne par code, la boucle est parcourue, pour une seule ligne, mais elle est déjà dans le bon format mais ce n'est pas génant)
    Les suggestions n'en tiennent pas compte.
    Citation Envoyé par noftal Voir le message
    Dans ce code modificatif, tu penses inutile de vérifier que la valeur de la propriété précédente était différente (If M.StarWidth <> value...) ?
    C'est juste un exemple d'utilisation, on peut l'utiliser ainsi puisque le UserControle fera le test, mais on peut aussi mettre le test avant de donner la valeur à la propriété (mais c'est pas vraiment utile).
    Par contre dans le UserControle, c'est bien de vérifier, là il le faut.


    Citation Envoyé par noftal Voir le message
    J'ai effectivement remarqué qu'il faut faire un DataGridView1.Refresh() dès lors que je modifie les propriétés par le code. Y a-t-il un moyen de s'en affranchir ?
    Oui, il suffit de mettre le refresh dans le UserControl
    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
        Public Property StarWidth() As Integer
            Get
                Return DirectCast(Me.CellTemplate, DataGridViewStarRateCell).StarWidth
            End Get
            Set(ByVal value As Integer)
                DirectCast(Me.CellTemplate, DataGridViewStarRateCell).StarWidth = value
                If Me.DataGridView IsNot Nothing Then
                    Dim cell As DataGridViewStarRateCell
                    For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                        cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                        If cell IsNot Nothing Then cell.StarWidth = value
                    Next
                    Me.DataGridView.Refresh()
                End If
            End Set
        End Property
    Traductions d'articles :
    La mémoire en .NET - Qu'est-ce qui va où ?
    Architecture DAL de haute performance et DTO ; Version C# : Partie 1,Partie 2,Partie 3 — Version VB.NET : Partie 1,Partie 2,Partie 3
    N'hésitez pas à consulter la FAQ VB.NET, le cours complet de Philippe Lasserre et tous les cours, articles et tutoriels.

  4. #24
    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
    Mais pour l'instant j'essaye de faire en sorte que le double click sur la bordure de la colonne du DTG provoque l'adaptation de la largeur au nombre max d'étoiles contenu dans la colonne. Ca n'a pas l'air simple cette histoire car il faut travailler sur une routine (que je n'ai pas encore identifié) de la classe DataGridview il me semble.
    Voici ce que j'ai trouvé : il faut créer une classe StarRateDataGridView héritée de DataGridView et modifier la sub OnColumnDividerDoubleClick :

    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
    Public Class StarRateDataGridView
        Inherits DataGridView
     
        Protected Overrides Sub OnColumnDividerDoubleClick(e As System.Windows.Forms.DataGridViewColumnDividerDoubleClickEventArgs)
            MyBase.OnColumnDividerDoubleClick(e)
            If TypeOf (Me.Columns(e.ColumnIndex)) Is DataGridViewStarRateColumn Then
                Dim starwidth As Integer = DirectCast(Me.Columns(e.ColumnIndex), DataGridViewStarRateColumn).StarWidth
                Dim maxvalue As Integer
                For rowIndex As Integer = 0 To Me.Rows.Count - 1
                    If CInt(Me.Rows(rowIndex).Cells(e.ColumnIndex).Value) > maxvalue Then maxvalue = CInt(Me.Rows.SharedRow(rowIndex).Cells(e.ColumnIndex).Value)
                Next
                Me.Columns(e.ColumnIndex).Width = maxvalue * starwidth
            End If
     
        End Sub
    End Class
    Ca marche bien, mais je ne suis pas entièrement satisfait :
    - ça m'oblige à changer tous mes DTG en StareRateDTG. L'idéal aurait été que je puisse rattacher la modification du comportement de l'événement "Double-Click sur bordure colonne" à la classe DataGridViewStarRateColumn. Je suppose que ce n'est pas possible à moins que qqun ait quelque chose à proposer.
    - Dans le code ci-desssus, je ne retrouve pas comment trouver simplement la valeur max d'une colonne de DTG. Du coup, j'ai recodé l'algo qui consiste à trouver le max. Je ne serais pas étonné qu'il y ait plus simple.

  5. #25
    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,

    J'ai pas tout suivi et j'ai pas vraiment le temps de rattraper mon retard mais concernant l'autosize de la colonne lors du double clique sur le séparateur de colonne, je pense qu'il doit y avoir un comportement à redéfinir dans la classe de la colonne custom car le code de la classe de la Sub OnColumnDividerDoubleClick de la classe DataGridView ne pas quelque chose de différent suivant le type de colonne (heureusement d'ailleurs !).

    Pour info, le code de la sub en question (obtenu à l'aide de .NET Reflector 8.3) :
    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
    
     
    Kropernic

  6. #26
    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
    car le code de la classe de la Sub OnColumnDividerDoubleClick de la classe DataGridView ne pas quelque chose de différent suivant le type de colonne (heureusement d'ailleurs !).
    Je n'ai pas compris ta phrase (coquille). Tu peux reformuler.
    J'ai bien réussi à mettre la main sur le code source de la procédure OnColumnDividerDoubleClick mais je n'ai pas réussi à aller plus loin dans sa réutilisation.

    En revanche, au moment où ton message m'a été notifié, j'ai finalisé la procédure customisé pour tenir compte du column header text et du cas où ma colonne est vide.

    Mes 2 précédentes questions demeurent cependant.

    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
    Protected Overrides Sub OnColumnDividerDoubleClick(e As System.Windows.Forms.DataGridViewColumnDividerDoubleClickEventArgs)
            MyBase.OnColumnDividerDoubleClick(e)
            Dim defaultcolumnwidth = Me.Columns(e.ColumnIndex).Width
            If TypeOf (Me.Columns(e.ColumnIndex)) Is DataGridViewStarRateColumn Then
                Dim starwidth As Integer = DirectCast(Me.Columns(e.ColumnIndex), DataGridViewStarRateColumn).StarWidth
                Dim maxvalue As Integer
                For rowIndex As Integer = 0 To Me.Rows.Count - 1
                    If CInt(Me.Rows(rowIndex).Cells(e.ColumnIndex).Value) > maxvalue Then maxvalue = CInt(Me.Rows.SharedRow(rowIndex).Cells(e.ColumnIndex).Value)
                Next
                If maxvalue <> 0 Then
                    Select Case Me.ColumnHeadersDefaultCellStyle.WrapMode
                        Case DataGridViewTriState.True 'retour à la ligne du columnheadertext autorisé
                            Me.Columns(e.ColumnIndex).Width = maxvalue * starwidth
                        Case Else 'retour à la ligne du columnheadertext interdit
                            Me.Columns(e.ColumnIndex).Width = Math.Max(maxvalue * starwidth, defaultcolumnwidth)
                    End Select
                End If
            End If
     
        End Sub

  7. #27
    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
    Ce que je voulais dire c'est que, vu que
    1. la classe DataGridView n'a pas un code bien spécifique à chaque type de colonne en cas de demande d'auto-resize (ie double clique sur le séparateur de colonne)
    2. tous types de colonnes déjà existantes se resize correctement

    C'est que le code provoquant se comportement qui est spécifique pour chaque type de colonne (une colonne normale se redimensionnera en fonction de son texte mais toutes les colonnes ne contiennent pas forcément du texte) est ailleurs. Reste plus qu'à trouver où et à reproduire la même chose pour ta classe StarRateColumn.

    Enfin je crois
    Kropernic

  8. #28
    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 partage ton analyse.
    Mais l'événement "double-click sur bordure colonne" est codé et piloté par la classe DataGridView.
    Donc je ne vois que 2 solutions avec mes modestes connaissances en VB.NET (et surtout en POO) :
    - overrider la procédure OnColumnDividerDoubleClick de cette classe comme j'ai fait
    - recoder dans ma classe DataGridViewStarRateColumn un événement analogue en allant chercher dans le Framework le code source du DTG comme tu l'as fait et en recopiant ce qui est utile. D'ailleurs, j'ai l'impression que le code clé se trouve plutôt dans la procédure AutoResizeRowHeadersWidth.

    à moins qu'il y ait une 3ème voie ?

    Pour ceux que ça intéresse, j'ai traduit AutoResizeRowHeadersWidth et OnColumnDividerDoubleClick en VB.NET

    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
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    Protected Overridable Sub OnColumnDividerDoubleClick(e As DataGridViewColumnDividerDoubleClickEventArgs)
            Dim eh As DataGridViewColumnDividerDoubleClickEventHandler = TryCast(Me.Events(EVENT_DATAGRIDVIEWCOLUMNDIVIDERDOUBLECLICK), DataGridViewColumnDividerDoubleClickEventHandler)
            If eh IsNot Nothing AndAlso Not Me.dataGridViewOper(DATAGRIDVIEWOPER_inDispose) AndAlso Not Me.IsDisposed Then
                eh(Me, e)
            End If
     
            If Not e.Handled AndAlso e.Button = MouseButtons.Left AndAlso e.ColumnIndex < Me.Columns.Count Then
                If e.ColumnIndex = -1 Then
                    'fixedColumnHeadersHeight
                    'fixedRowsHeight
                    AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders, True, True)
                Else
                    Dim inheritedAutoSizeMode As DataGridViewAutoSizeColumnMode = Me.Columns(e.ColumnIndex).InheritedAutoSizeMode
                    If inheritedAutoSizeMode = DataGridViewAutoSizeColumnMode.None OrElse inheritedAutoSizeMode = DataGridViewAutoSizeColumnMode.Fill Then
                        'fixedHeight
                        AutoResizeColumnInternal(e.ColumnIndex, DataGridViewAutoSizeColumnCriteriaInternal.Header Or DataGridViewAutoSizeColumnCriteriaInternal.AllRows, True)
                    Else
                        'fixedHeight
                        AutoResizeColumnInternal(e.ColumnIndex, DirectCast(inheritedAutoSizeMode, DataGridViewAutoSizeColumnCriteriaInternal), True)
                    End If
                End If
            End If
        End Sub
     
     
     
     
        Protected Sub AutoResizeRowHeadersWidth(rowHeadersWidthSizeMode As DataGridViewRowHeadersWidthSizeMode, fixedColumnHeadersHeight As Boolean, fixedRowsHeight As Boolean)
            If rowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.EnableResizing OrElse rowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing Then
                Throw New ArgumentException(SR.GetString(SR.DataGridView_NeedAutoSizingCriteria, "rowHeadersWidthSizeMode"))
            End If
            ' custom range checking, not using ClientUtils. 
            If rowHeadersWidthSizeMode < DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders OrElse rowHeadersWidthSizeMode > DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader Then
                Throw New InvalidEnumArgumentException("rowHeadersWidthSizeMode", CInt(rowHeadersWidthSizeMode), GetType(DataGridViewRowHeadersWidthSizeMode))
            End If
     
     
            If Not Me.RowHeadersVisible Then
                Return
            End If
     
            If Not Me.IsHandleCreated Then
                ' auto sizing causes handle creation.
                ' don't create the handle inside InitializeComponent because that causes problems w/ data binding 
                Me.dataGridViewState2(DATAGRIDVIEWSTATE2_autoSizedWithoutHandle) = True
                Return
            End If
     
            Try
                Me.noAutoSizeCount += 1
                ' Use of WindowsFormsUtils.CreateMeasurementGraphics() avoid use of this.Handle
                ' IntPtr handle = this.Handle; // Force creation of control's handle because for databound grids, handle creation wipes out and recreates the columns/rows. 
                Dim preferredWidth As Integer = 0, rowIndex As Integer
                If Me.layout.TopLeftHeader.Width > 0 Then
                    If fixedColumnHeadersHeight Then
                        preferredWidth = Me.TopLeftHeaderCell.GetPreferredWidth(-1, Me.layout.TopLeftHeader.Height)
                    Else
                        preferredWidth = Me.TopLeftHeaderCell.GetPreferredSize(-1).Width
                    End If
                End If
                Select Case rowHeadersWidthSizeMode
                    Case DataGridViewRowHeadersWidthSizeMode.AutoSizeToFirstHeader
                        If True Then
                            rowIndex = Me.Rows.GetFirstRow(DataGridViewElementStates.Visible)
                            If rowIndex <> -1 Then
                                If fixedRowsHeight Then
                                    preferredWidth = Math.Max(preferredWidth, Me.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, Me.Rows.SharedRow(rowIndex).GetHeight(rowIndex)))
                                Else
                                    preferredWidth = Math.Max(preferredWidth, Me.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width)
                                End If
                            End If
                            Exit Select
                        End If
                    Case DataGridViewRowHeadersWidthSizeMode.AutoSizeToDisplayedHeaders
                        If True Then
                            Dim displayHeight As Integer = Me.layout.Data.Height, cy As Integer = 0
                            rowIndex = Me.Rows.GetFirstRow(DataGridViewElementStates.Visible Or DataGridViewElementStates.Frozen)
                            While rowIndex <> -1 AndAlso cy < displayHeight
                                Dim dataGridViewRow As DataGridViewRow = Me.Rows.SharedRow(rowIndex)
                                Dim dataGridViewRowHeight As Integer = dataGridViewRow.GetHeight(rowIndex)
                                cy += dataGridViewRowHeight
                                If fixedRowsHeight Then
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight))
                                Else
                                    preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width)
                                End If
                                rowIndex = Me.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible Or DataGridViewElementStates.Frozen)
                            End While
                            If cy < displayHeight Then
                                rowIndex = Me.displayedBandsInfo.FirstDisplayedScrollingRow
                                While rowIndex <> -1 AndAlso cy < displayHeight
                                    Dim dataGridViewRow As DataGridViewRow = Me.Rows.SharedRow(rowIndex)
                                    Dim dataGridViewRowHeight As Integer = dataGridViewRow.GetHeight(rowIndex)
                                    cy += dataGridViewRowHeight
                                    If fixedRowsHeight Then
                                        preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredWidth(rowIndex, dataGridViewRowHeight))
                                    Else
                                        preferredWidth = Math.Max(preferredWidth, dataGridViewRow.HeaderCell.GetPreferredSize(rowIndex).Width)
                                    End If
                                    rowIndex = Me.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)
                                End While
                            End If
                            Exit Select
                        End If
                    Case DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders
                        If True Then
                            rowIndex = Me.Rows.GetFirstRow(DataGridViewElementStates.Visible)
                            While rowIndex <> -1
                                If fixedRowsHeight Then
                                    preferredWidth = Math.Max(preferredWidth, Me.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredWidth(rowIndex, Me.Rows.SharedRow(rowIndex).GetHeight(rowIndex)))
                                Else
                                    preferredWidth = Math.Max(preferredWidth, Me.Rows.SharedRow(rowIndex).HeaderCell.GetPreferredSize(rowIndex).Width)
                                End If
                                rowIndex = Me.Rows.GetNextRow(rowIndex, DataGridViewElementStates.Visible)
                            End While
                            Exit Select
                        End If
                    Case Else
                        If True Then
                            Debug.Fail("Unexpected rowHeadersWidthSizeMode value in AutoResizeRowHeadersWidth")
                            Exit Select
                        End If
                End Select
                If preferredWidth < minimumRowHeadersWidth Then
                    preferredWidth = minimumRowHeadersWidth
                End If
                If preferredWidth <> Me.RowHeadersWidth Then
                    Me.RowHeadersWidthInternal = preferredWidth
                End If
            Finally
                Debug.Assert(Me.noAutoSizeCount > 0)
                Me.noAutoSizeCount -= 1
            End Try
        End Sub
    EDIT : peut-être une piste avec OnDataGridViewChanged, la seule routine que l'on peut overrider dans DataGridViewStarRateColumn ayant, de loin, rapport avec l'événement double click sur les bordures.

  9. #29
    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
    Citation Envoyé par noftal Voir le message
    Je partage ton analyse.
    Mais l'événement "double-click sur bordure colonne" est codé et piloté par la classe DataGridView.
    Donc je ne vois que 2 solutions avec mes modestes connaissances en VB.NET (et surtout en POO) :
    - overrider la procédure OnColumnDividerDoubleClick de cette classe comme j'ai fait
    - recoder dans ma classe DataGridViewStarRateColumn un événement analogue en allant chercher dans le Framework le code source du DTG comme tu l'as fait et en recopiant ce qui est utile. D'ailleurs, j'ai l'impression que le code clé se trouve plutôt dans la procédure AutoResizeRowHeadersWidth.
    Sauf que le code de la classe DTG s'appuie apparemment sur la propriété InheritedAutoSizeMode de la colonne. T'as essayé de jouer avec ça pour voir ce que cela donne ?
    Kropernic

  10. #30
    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 une idée... sûrement à la con
    Je découvre que la classe DataGridViewElement possède une propriété nommée DataGridView de type DataGridView.

    Or, DataGridViewElement est la classe à la base de tous les types de colonnes (si on remonte la chaîne d'héritage).

    Ne serait-il pas alors possible, dans ta classe StarRateColumn de s'abonner à l'événement OnColumnDividerDoubleClick du DataGridView pour y faire le resize convenablement ? En prenant soin de vérifier que c'est bien sur le séparateur de ta colonne qu'on a double-cliqué.

    Ce n'est probablement pas le plus propre et je ne sais même pas si ça fonctionne mais bon, je propose quand même.
    Kropernic

  11. #31
    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 vois l'idée, mais comment se traduit le terme "s'abonner à " ?

  12. #32
    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
    Citation Envoyé par noftal Voir le message
    Je vois l'idée, mais comment se traduit le terme "s'abonner à " ?

    Par AddHandler ^^.

    Par contre, je viens de tester et à première vue ça ne passe pas. Si j'ai bien compris, ce serait parce que la propriété DataGridView n'est pas déclarée avec WithEvents :-/
    Dommage, ça aurait pu être cool.

    Mais bon, je reste persuadé qu'il doit y avoir un autre moyen que de devoir dériver la classe DTG de base...
    Kropernic

  13. #33
    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 crois avoir trouvé une solution :

    Dans la classe DataGridViewStarRate, rajouter ceci :

    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
     Public Overrides Function GetPreferredWidth(autoSizeColumnMode As System.Windows.Forms.DataGridViewAutoSizeColumnMode, fixedHeight As Boolean) As Integer
            GetPreferredWidth = MyBase.GetPreferredWidth(autoSizeColumnMode, fixedHeight)
            Dim defaultcolumnwidth = GetPreferredWidth
            Dim starwidth As Integer = Me.StarWidth
            Dim maxvalue As Integer
            For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                If CInt(Me.DataGridView.Rows(rowIndex).Cells(Me.Index).Value) > maxvalue Then maxvalue = CInt(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index).Value)
            Next
            If maxvalue <> 0 Then
                Select Case Me.DataGridView.ColumnHeadersDefaultCellStyle.WrapMode
                    Case DataGridViewTriState.True 'retour à la ligne du columnheadertext autorisé
                        GetPreferredWidth = maxvalue * starwidth 'on ne tient pas compte du header
                    Case Else 'retour à la ligne du columnheadertext interdit
                        GetPreferredWidth = Math.Max(maxvalue * starwidth, defaultcolumnwidth)
                End Select
            End If
     
        End Function
    Bien sûr plus besoin de customiser la classe DataGridView.

    J'ai eu la puce à l'oreille en regardant de près la procédure .NET AutoResizeRowHeadersWidth où il est question de "PreferredWith".
    Je pense donc que la procédure OnColumnDividerDoubleClick utilise à un moment la fonction GetPreferredWidth de la classe DTGColumn.
    En passant beaucoup de temps sur le code Framework, on pourrait le vérifier.
    Mais l'essentiel est que ça marche.
    Bien sûr n'hésitez pas à me faire part de vos commentaires.

  14. #34
    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
    La méthode de la classe DTG qui s'occupe de l'event OnColumnDividerDoubleClick fait appel à la méthode AutoResizeColumnInternal qui elle utilise PreferredWidth.

    Bien joué
    Kropernic

  15. #35
    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
    Voici la classe complète, déverminée de quelques imperfections et avec la possibilité de choisir sa propre image en lieu et place de l'image par défaut stockée dans My.resources.star_xxl


    Je pense qu'en cherchant bien, il doit encore y avoir des bogues, que j'espère mineurs. Avis aux amateurs.

    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
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    Imports System.Drawing
    Imports System.Windows.Forms
    Imports System.Windows.Forms.VisualStyles
    Imports System.ComponentModel
     
     
     
    Public Class DataGridViewStarRateColumn
        Inherits DataGridViewTextBoxColumn
     
        Public Sub New()
            Me.CellTemplate = New DataGridViewStarRateCell()
     
        End Sub
     
        <Category("Design")>
     <Description("Largeur de l'étoile")>
        Public Property StarWidth() As Integer
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarWidth
            End Get
     
            Set(ByVal value As Integer)
                If Me.StarWidth <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarWidth = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarWidth = value
                        Next
                        Me.DataGridView.Refresh()
                    End If
                End If
            End Set
        End Property
     
        <Category("Design")>
    <Description("Hauteur de l'étoile")>
        Public Property StarHeight() As Integer
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarHeight
            End Get
            Set(value As Integer)
                If Me.StarHeight <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarHeight = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarHeight = value
                        Next
                        Me.DataGridView.Refresh()
                    End If
                End If
            End Set
        End Property
     
        <Category("Design")>
    <Description("Alignement des étoiles dans la cellule")>
        Public Property StarAlignment() As DataGridViewContentAlignment
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarAlignment
            End Get
            Set(value As DataGridViewContentAlignment)
                If Me.StarAlignment <> value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarAlignment = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarHeight = value
                        Next
                        Me.DataGridView.Refresh()
                    End If
                End If
            End Set
        End Property
     
        <Category("Design")>
    <Description("Image de l'étoile")>
        Public Property StarImage() As Image
            Get
                If DirectCast(CellTemplate, DataGridViewStarRateCell) Is Nothing Then
                    Throw New InvalidOperationException("cell template required")
                End If
                Return DirectCast(CellTemplate, DataGridViewStarRateCell).StarImage
            End Get
            Set(value As Image)
                If Me.StarImage IsNot value Then
                    DirectCast(CellTemplate, DataGridViewStarRateCell).StarImage = value
                    If Me.DataGridView IsNot Nothing Then
                        Dim cell As DataGridViewStarRateCell
                        For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                            cell = TryCast(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index), DataGridViewStarRateCell)
                            If cell IsNot Nothing Then cell.StarImage = value
                        Next
                        Me.DataGridView.Refresh()
                    End If
                End If
     
            End Set
        End Property
     
     
     
        Public Overrides Function GetPreferredWidth(autoSizeColumnMode As System.Windows.Forms.DataGridViewAutoSizeColumnMode, fixedHeight As Boolean) As Integer
            GetPreferredWidth = MyBase.GetPreferredWidth(autoSizeColumnMode, fixedHeight)
            Dim defaultcolumnwidth = GetPreferredWidth
            Dim starwidth As Integer = Me.StarWidth
            Dim maxvalue As Integer
            For rowIndex As Integer = 0 To Me.DataGridView.Rows.Count - 1
                If CInt(Me.DataGridView.Rows(rowIndex).Cells(Me.Index).Value) > maxvalue Then maxvalue = CInt(Me.DataGridView.Rows.SharedRow(rowIndex).Cells(Me.Index).Value)
            Next
            If maxvalue <> 0 Then
                Select Case Me.DataGridView.ColumnHeadersDefaultCellStyle.WrapMode
                    Case DataGridViewTriState.True 'retour à la ligne du columnheadertext autorisé
                        GetPreferredWidth = maxvalue * starwidth 'on ne tient pas compte du header
                    Case Else 'retour à la ligne du columnheadertext interdit
                        GetPreferredWidth = Math.Max(maxvalue * starwidth, defaultcolumnwidth)
                End Select
            End If
     
        End Function
     
    End Class
     
     
     
    Public Class DataGridViewStarRateCell
        Inherits DataGridViewTextBoxCell
     
        Private _starwidth As Integer = 20
        Private _starheight As Integer = 20
        Private _staralignment As DataGridViewContentAlignment = DataGridViewContentAlignment.TopLeft
        Private _image As Image = My.Resources.star_xxl 'une étoile
        Const KminValue As Integer = 5
     
     
        Public Property StarWidth() As Integer
            Get
                Return _starwidth
            End Get
            Set(ByVal value As Integer)
                If value < KminValue Then _starwidth = KminValue Else _starwidth = value
            End Set
        End Property
     
     
        Public Property StarHeight() As Integer
            Get
                Return _starheight
            End Get
            Set(ByVal value As Integer)
                If value < KminValue Then _starheight = KminValue Else _starheight = value
            End Set
        End Property
     
     
        Public Property StarAlignment() As DataGridViewContentAlignment
            Get
                Return _staralignment
            End Get
            Set(ByVal value As DataGridViewContentAlignment)
                _staralignment = value
            End Set
        End Property
     
        Public Property StarImage() As Image
            Get
                Return _image
            End Get
            Set(value As Image)
                _image = value
            End Set
        End Property
     
        Public Overrides Function Clone() As Object
            Dim Cell As DataGridViewStarRateCell = DirectCast(MyBase.Clone(), DataGridViewStarRateCell)
            Cell.StarWidth = Me.StarWidth
            Cell.StarHeight = Me.StarHeight
            Cell.StarAlignment = Me.StarAlignment
            Cell.StarImage = Me.StarImage
            Return Cell
        End Function
     
     
        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 the stars look good at any size)
            graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
     
            ' dessine le nombre d'étoiles correspondant à la valeur de la cellule
            ' le dessin est limité aux dimensions de la cellule
            Dim starValue As Integer 'valeur de la note
            Dim filledtouse As Image = _image
            Dim height As Integer = filledtouse.Height
            Dim width As Integer = filledtouse.Width
            Dim destRectX, destRectY, destRectWidth, destRectHeight As Integer
            Dim srcRectWidth, srcRectHeight As Integer
            Dim destRect, srcRect As Rectangle
            Dim oAlignment As DataGridViewContentAlignment
            Dim sTronq As String = "..."
            Dim sTronqSize As SizeF = graphics.MeasureString(sTronq, cellStyle.Font)
            Dim iTronq As Single
            starValue = CInt(value)
            ' réglage alignement des étoiles dans la cellule
            Dim offsetX, offsetY As Integer
            Select Case _staralignment
                Case DataGridViewContentAlignment.BottomCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.BottomLeft
                    offsetX = 0 'left
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.BottomRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = Math.Max(0, (cellBounds.Height - _starheight)) 'Bottom
                    oAlignment = DataGridViewContentAlignment.BottomRight
                Case DataGridViewContentAlignment.MiddleCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.MiddleLeft
                    offsetX = 0 'left
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.MiddleRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = CInt(Math.Max(0, (cellBounds.Height - _starheight) / 2)) ' Middle
                    oAlignment = DataGridViewContentAlignment.MiddleRight
                Case DataGridViewContentAlignment.TopCenter
                    offsetX = CInt(Math.Max(0, (cellBounds.Width - starValue * _starwidth) / 2)) ' Center
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
                Case DataGridViewContentAlignment.TopLeft, DataGridViewContentAlignment.NotSet
                    offsetX = 0 'left
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
                Case DataGridViewContentAlignment.TopRight
                    offsetX = Math.Max(0, cellBounds.Width - starValue * _starwidth) 'Right
                    offsetY = 0 'top
                    oAlignment = DataGridViewContentAlignment.TopRight
            End Select
     
            If _starwidth * starValue > cellBounds.Width Then ' La taille de la cellule est insuffisante pour tout afficher
                cellStyle.Alignment = oAlignment
                iTronq = sTronqSize.Width + 3 'padding right estimé à 3
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, sTronq, sTronq, errorText, cellStyle, advancedBorderStyle, paintParts)
            Else
                iTronq = 0
                MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, elementState, Nothing, Nothing, errorText, cellStyle, advancedBorderStyle, paintParts)
            End If
     
            For i = 1 To starValue
                destRectX = cellBounds.X + offsetX + (i - 1) * _starwidth
                destRectY = cellBounds.Y + offsetY
                destRectWidth = Math.Min(_starwidth, cellBounds.Width - (i - 1) * _starwidth - CInt(iTronq)) - 1
                destRectHeight = Math.Min(cellBounds.Height, _starheight) - 1
                srcRectWidth = CInt(width / _starwidth * destRectWidth)
                srcRectHeight = CInt(height * Math.Min(cellBounds.Height / _starheight, 1))
                destRect = New Rectangle(destRectX, destRectY, destRectWidth, destRectHeight)
                srcRect = New Rectangle(0, 0, srcRectWidth, srcRectHeight)
                graphics.DrawImage(filledtouse, destRect, srcRect, GraphicsUnit.Pixel)
            Next
     
     
        End Sub
     
    End Class

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 10
    Dernier message: 27/10/2014, 14h50
  2. Binder un élément et pas une propriété
    Par Flaburgan dans le forum Windows Presentation Foundation
    Réponses: 11
    Dernier message: 27/02/2013, 16h37
  3. Réponses: 11
    Dernier message: 23/05/2011, 03h26
  4. Réponses: 1
    Dernier message: 08/11/2010, 12h24
  5. Réponses: 1
    Dernier message: 08/01/2009, 12h23

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