User control pour un histogramme à barres verticales

Contenu du snippet

A partir d'un User Control (U_C) on veut un Histogramme à Barres Verticales (version 4) en utilisant des Label et des PictureBox

Les props Read sont accessibles depuis la boite à outils du U_C dans l'Appli_Cliente (Echelle, Maxi...)
Les props Write ne sont accessible que depuis le code de l'Appli_Cliente (GO)
ci dessous les deux pages de code : l'Appli_Cliente puis le User_Control

Source / Exemple :


Public Class Form1
    ' ===== Application_Cliente utilisant un User Control = Histogramme à Barres Verticales (Version 4)  

    Private arrColor() As Color = {Color.Tomato, Color.DarkSeaGreen, Color.CornflowerBlue, _
                                   Color.Orchid, Color.OliveDrab, Color.SlateBlue, Color.Goldenrod, Color.Tan}
    Private table1902 As New DataTable, table1903 As New DataTable
    Private array1902() As Integer = {75, 300, 40, 250, 8, 165, 15}
    Private array1903() As Integer = {50, 280, 10, 350, 40, 75, 2}
    Private arrayNom() As String = {"Dijon", "Nantes", "Nice", "Paris", "Lyon", "Cherbourg", "Pau"}

    ' ===== Paramétrage du U_C et lancement du Traitement des Données :
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Charger_Table(table1902, array1902, arrayNom) ' on fait comme pour convertir un RecordSet en DataTable
        Charger_Table(table1903, array1903, arrayNom)
        With UC_Histo_1902
            ' ----- les props READ peuvent être valorisées dans la Boite de Props de cette Form :
            '   .HauteurGraphique = 400
            '   .MaxValue = 400
            '   .Echelle = 40                       ' Quand Echelle = 0 on n'affiche que la valeur MAXI
            '   .LargeurBarre = 40                  ' Facultatif = par défaut = 25
            '   .Titre_Graphique = "Conso Radis 1902"
            '   .Unite = "tonnes"   
            ' ----- les Props WRITE sont gérées par le U_C
            .Table_Serie = table1902
            .array_Couleurs = arrColor
            .Left = 20                           ' positon du U_C ici, dans l'Appli_Cliente
            ' ----- et on déclenche l'évenement Load PUBLIC de ce U_C (Go dans le U_C)
            .Go(sender, e)
        End With
        ' ----- ce qui donne pour faire court :
        With Uc_Histo_1903
            .Table_Serie = table1903
            .array_Couleurs = arrColor
            .Left = UC_Histo_1902.Width + 40
            .Go(sender, e)
        End With
    End Sub
    ' ===== Charger les tables (idem from RecordSet de BdD) :
    Private Function Charger_Table(ByVal _table As DataTable, ByVal _Val As Array, ByVal _Leg As Array) As Boolean
        Dim R As DataRow
        With _table
            .Columns.Add() : .Columns.Add()
            For i As Integer = 0 To 6 ' ici une limite arbitraire pour l'exemple
                R = .NewRow
                R(0) = _Leg(i) : R(1) = _Val(i)
                .Rows.Add(R) ' et on suppose pour l'exercice que les données sont cohérentes !
            Next
        End With
        Return _table.Rows.Count
    End Function
    ' ===== TCHCONST jan 2011 =====
End Class
----------  Le User Control ----------
Public Class uc_Histo_V3

    ' ===== CDC : User_Control qui construit un Histogramme à Barres Verticales 
    '             en utilisant seulement des Label et des PictureBox - TCHCONST jan 2011 -  

    ' ===== Variables et Propriétés  
    Private graphHauteur, Maxi, Echelle As Integer
    Private barreLargeur As Integer = 25
    Private interval As Integer = 0
    Private Units As String = "unités"
    Private Titre As String = "HistoGramme" ' ou Message d'Erreur
    Private Serie As DataTable
    Private arrColors As Array
    Private Erreur As Boolean = False
    Public Property Titre_Graphique() As String
        Get
            Return Titre
        End Get
        Set(ByVal value As String)
            Titre = value
        End Set
    End Property
    Public Property Unite() As String
        Get
            Return Units
        End Get
        Set(ByVal value As String)
            Units = value
        End Set
    End Property
    Public Property Max_Value() As Integer
        Get
            Return Maxi
        End Get
        Set(ByVal value As Integer)
            Maxi = value
        End Set
    End Property
    Public Property Echelle_Valeurs() As Integer
        Get
            Return Echelle
        End Get
        Set(ByVal value As Integer)
            Echelle = value
        End Set
    End Property
    Public Property Hauteur_Graphique() As Integer
        Get
            Return graphHauteur
        End Get
        Set(ByVal value As Integer)
            graphHauteur = value
        End Set
    End Property
    Public Property Largeur_Barre() As Integer
        Get
            Return barreLargeur
        End Get
        Set(ByVal value As Integer)
            barreLargeur = value
        End Set
    End Property
    Public Property Interval_Barre() As Integer
        Get
            Return interval
        End Get
        Set(ByVal value As Integer)
            interval = value
        End Set
    End Property
    Public WriteOnly Property Table_Serie() As DataTable
        Set(ByVal value As DataTable)
            Serie = value
        End Set
    End Property
    Public WriteOnly Property array_Couleurs() As Array
        Set(ByVal value As Array)   ' c'est dans l'Appli_Cliente que l'on s'assure de la cohérence Série > Couleurs 
            arrColors = value
        End Set
    End Property

    ' ===== Création des controles constitutifs et Traitement des données (ici l'evt Load est PUBLIC) 

    Public Sub Go(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Serie Is Nothing Then Exit Sub
        Dim nbBarres, i As Integer
        ' vérifier les paramètres (gestion erreur LIGHT) :
        If graphHauteur < 100 Then Erreur = True : Titre = "Hauteur Histo incohérente"
        nbBarres = Serie.Rows.Count
        If nbBarres = 0 Then Erreur = True : Titre = "Série incohérente"
        If Maxi = 0 Then Erreur = True : Titre = "Max incohérent"
        If Maxi < Echelle Then Erreur = True : Titre = "Echelle incohérente"
        ' NB : nous avons 1 controle dans le [Design] L_Titre(Label) pour le titre ou la gestion d'Erreur
        Dim L As Label                  ' label pour toutes les valeurs
        Dim P As PictureBox             ' niveaux, barres, graph, nuancier    

        If Not Erreur Then

            Dim barreColor, fontColor, graphColor As Color
            Dim fontTexte As New Font("Verdana", 10)
            Dim fontVal As New Font("Verdana", 8, FontStyle.Bold)
            Dim maVal As Integer
            Dim monTxt As String

            ' ----- 1) Formatage Général 
            Dim lblHauteur, ctlTop, ctlHauteur, cptLeft, cptBas As Integer
            Dim nbEchelons, interEchelon, Marge, margeGauche, graphLargeur, margeDroite As Integer
            graphLargeur = (nbBarres * barreLargeur) + ((nbBarres - 1) * interval)
            L_Titre.Text = Maxi                     ' valeur témoin pour la largeur de la Marge Gauche 
            L_Titre.Font = fontVal
            L_Titre.FlatStyle = 3 : L_Titre.AutoSize = True
            margeGauche = L_Titre.Width
            lblHauteur = L_Titre.Height             ' hauteur témoin d'une étiquette
            Marge = Math.Round(lblHauteur / 2)      ' les marges autour des divers controles

            ' ----- 2) Afficher l'Echelle ou la Valeur Maxi ?
            If Echelle > 0 And Maxi > 0 Then
                nbEchelons = Math.Round(Maxi / Echelle)
                interEchelon = Math.Round(graphHauteur / Maxi * Echelle)
                For i = 0 To nbEchelons
                    ' ----- 2.1) Valeur dans la marge gauche 
                    monTxt = (Echelle * i).ToString
                    ctlTop = graphHauteur - (interEchelon * i)
                    L = New Label With {.Top = ctlTop, .Left = 0, .Width = margeGauche, _
                                        .Text = monTxt, .Font = fontVal, .TextAlign = 4}
                    ' ----- 2.2) Barre de niveau dans le cadre du graphique  
                    P = New PictureBox With {.Top = ctlTop + Marge, .Left = margeGauche, _
                                             .Width = graphLargeur, .Height = 1, .BackColor = Color.Wheat}
                    Controls.Add(L) : Controls.Add(P)
                Next
            Else
                ' ----- 2.bis) Maxi seulement 
                L = New Label With {.Top = 0, .Left = 0, .ForeColor = Color.Black, .Text = Maxi, _
                                    .Width = margeGauche, .Font = fontVal, .TextAlign = 4, .FlatStyle = 3}
                Controls.Add(L)
            End If

            ' ----- 3) Barres de la Série et Valeurs 
            If Not arrColors Is Nothing Then
                If arrColors.Length > nbBarres Then
                    graphColor = arrColors(nbBarres) ' la couleur du fond du graphique demandée 
                Else
                    graphColor = Color.White : barreColor = Color.LightGray ' ou par défaut 
                End If
            Else ' toutes les couleurs par défaut 
                barreColor = Color.LightGray : fontColor = Color.Black : graphColor = Color.Tan
            End If
            cptLeft = margeGauche
            With Serie
                For i = 0 To nbBarres - 1
                    monTxt = .Rows(i).Item(0) : maVal = .Rows(i).Item(1)
                    ' ----- 3.1) Barre
                    ctlHauteur = Math.Round(graphHauteur / Maxi * .Rows(i).Item(1))
                    ctlTop = Marge + graphHauteur - ctlHauteur
                    If ctlHauteur > graphHauteur Then                    ' le max est incohérent, erreur déjà levée !
                        ctlTop = Marge
                        ctlHauteur = graphHauteur
                        If Not Erreur Then Titre = String.Format("Maxi={0} < {1}={2}", Max_Value, monTxt, maVal)
                        Erreur = True
                    End If
                    If Not arrColors Is Nothing Then barreColor = arrColors(i)
                    P = New PictureBox With {.Left = cptLeft, .Top = ctlTop, .Width = barreLargeur, _
                                             .Height = ctlHauteur, .BackColor = barreColor, .Cursor = Cursors.Hand}
                    ' ----- 3.2) Valeur sous le Top de la barre, ou au dessus si la barre < hauteur de police 
                    If ctlHauteur < fontVal.GetHeight Then
                        ctlTop -= fontVal.GetHeight
                        barreColor = graphColor : fontColor = Color.Black
                    Else
                        fontColor = Color.White
                    End If
                    L = New Label With {.Left = cptLeft, .Top = ctlTop, .Width = barreLargeur, .BackColor = barreColor, _
                                        .ForeColor = fontColor, .Text = maVal, .TextAlign = 2, .FlatStyle = 3, _
                                        .Font = fontVal, .Height = fontVal.GetHeight, .Cursor = Cursors.Hand}
                    Controls.Add(P) : Controls.Add(L)
                    ' ----- 3.3) Bulles et premier-plan 
                    P.BringToFront() : L.BringToFront()
                    monTxt = String.Format(" {0} {1} {2} ", monTxt, maVal, Units)
                    ttip.SetToolTip(P, monTxt) : ttip.SetToolTip(L, monTxt)
                    cptLeft += barreLargeur + interval
                Next

                ' ----- 4) Titre du Graphique ou Erreur
                With L_Titre
                    .Font = fontTexte
                    If Erreur Then
                        .Text = "erreur: " & Titre
                    Else
                        .Text = String.Format("{0} ({1})", Titre, Units)
                    End If
                    .Left = margeGauche : .Top = graphHauteur + lblHauteur
                    .TextAlign = 16 : .FlatStyle = 3 : .AutoSize = True
                End With

                ' ----- 5) Légende en bas à droite 
                cptLeft += Marge - interval
                cptBas = Marge + graphHauteur
                For i = nbBarres - 1 To 0 Step -1           ' en partant de la base du graphique 
                    If arrColors Is Nothing Then
                        barreColor = Color.LightGray        ' couleur de la barre par défaut 
                    Else
                        barreColor = arrColors(i)
                    End If
                    ' ----- 5.1) Nuancier = Carrés de 12x12  
                    P = New PictureBox With {.Top = cptBas - 12, .Left = cptLeft, .Width = 12, .Height = 12, _
                                             .BackColor = barreColor, .Cursor = Cursors.Hand}
                    ' ----- 5.2) Etiquette
                    monTxt = String.Format(" {0} ", .Rows(i).Item(0))
                    L = New Label With {.Top = cptBas - lblHauteur, .Left = cptLeft + 10, .Text = monTxt, _
                                        .Cursor = Cursors.Hand, .TextAlign = 256, .FlatStyle = 3, .AutoSize = True}
                    Controls.Add(P) : Controls.Add(L)
                    ' ----- 5.3) Bulle et marge Droite 
                    monTxt = String.Format(" {0} {1} {2} ", .Rows(i).Item(0), .Rows(i).Item(1), Units)
                    ttip.SetToolTip(P, monTxt) : ttip.SetToolTip(L, monTxt)
                    If L.Width > margeDroite Then margeDroite = L.Width
                    cptBas -= (lblHauteur + 2)
                Next
                margeDroite += 12 + (Marge * 3)
            End With

            ' ----- 6) Cadre de fond du graphique 
            P = New PictureBox With {.Top = Marge, .Left = margeGauche, .Width = graphLargeur, _
                                    .Height = graphHauteur, .BackColor = graphColor}
            Controls.Add(P) : P.SendToBack()

            ' ----- 7) Dimensions finales du U_C 
            Width = cptLeft + margeDroite
            Height = graphHauteur + (lblHauteur * 2.5)

        Else

            ' ----- 8) Erreurs !!! 
            With L_Titre
                .Text = "erreur: " & Titre
                .Left = 0 : .Width = 300
            End With
            Width = 300
        End If
    End Sub
    ' ===== TCHCONST jan 2011 =====
End Class

Conclusion :


Dans ce U_C aucun contrôle ne déclenche un quelconque événement.
Pour gérer les contrôles constitutifs et les données, on déclenche depuis l'Appli_Cliente l'événement Load du U_C qui est Public.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.