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 :

Comment créer une colonne dynamique d'items ?


Sujet :

VB.NET

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut Comment créer une colonne dynamique d'items ?
    Bonjour

    Le principe est de créer une colonne unidimensionnelle, sans en-tete de colonne/ligne, contenant initialement une seule combobox dont le .Text = "" et dont la liste déroulante contient tous les enregistrements du champ "Names" d'une Datatable exisstante. Cette Datatable a également un champ "Coût" pour chacun de ses items.
    Un Label au dessus de cette colonne affichera "X/50", où X représente la somme des "coûts" de chaque item si selectionné.

    Lorque l'utilisateur sélectionne 1 item dans cette 1ère combobox :
    - la valeur X est incrémentée avec le coût de l'item sélectionné
    - une nouvelle combo apparait juste en dessous avec sa liste déroulante contenant les mêmes items sauf celui qui a déjà été selectionné ET sans les items dont le coût est > à 50 - X.

    Au final l'utilisateur aura donc une liste d'items dont le nombre sera limité par le coût total autorisé (50).

    A priori, j'ai pensait créer un DataGridViiew monocolonne de type DataGridViewComboxColumn. Puis d'utiliser un Dataview de la Datatable dont le rowfilter serait dynamique avec la valeur de la combo précédente. Et enfin d'affecter ce dataview a la propriété Datasource de la comboboxcell courante.

    Je n'ai pas eu de problème pour créer la dgv et sa DGVcombocolumn, mais :
    - PB1: ce n'est pas un combobox mais un dropdownbutton alors que j'aurais préféré un "vrai" combobox avec autocompletion...
    - PB2: au niveau syntaxe, si ma dgvcombocolumn s'appelle "Column1" et que je tape dans mon Main_Load quelle propriété faut-il utiliser pour cibler la bonne comboboxcell puis ensuite quelle propiété utiliser pour "datasource" et "displaymember" ? VB2010 me dit que ces propriétés n'existent pas... du coup je suis bien emmerdé pour affecter ma dataview dynamique...

    L'autre possibilité auquel j'ai pensé etait d'ajouter au DGV non pas un DGVcomboboxcolumn mais un KryptonDGVcomboboxcolumn (free toolkit de ComponentFactory) qui lui est un "vrai" comboboxcell, cela resout le PB1 expliqué ci-dessus, mais le PB2 reste...

    donc me voilà a venir poster ici pour demander si quelqu'un aurait une meilleure idée du point de vue conceptuel, ou saurait la bonne syntaxe pour le PB2 ?

    Merci d'avance.

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    il y a plein de moyens de faire ca en plus simple, les combobox personnellement je suis pas fan, pour l'utilisateur c'est super chiant

    tu peux faire 2 datagrids, celui de gauche avec tous les items et leur cout (2 colonnes), celui de droite avec la selection et en haut un label disant x/50
    un drag drop de gauche à droite et tu retires un items dans le dg de gauche et tu le rajoutes à droite (et inversement)
    avec possibilité de tri sur le nom et le cout de chaque coté
    ceux qui ont un cout supérieur à ce qu'il est possible de rajouter tu les grises

    en wpf ca serait très simple à écrire (et plus joli que 2 datagrids) avec 2 listbox et un template, en windows forms ca risque de prendre plus de lignes de code


    autre méthodes sans les datagrid, un flowlayoutpanel avec autoscroll à true dans lequel tu add des combobox, ca correspond plus à ce que tu recherches, mais moins à ce qu'un utilisateur recherche
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Re bonjour Pol63

    Merci de ton interet à mes topics ^^

    Oui j'avoue que c chiant les comboboxs (pour utilisateur) mais bon quand tu dois choisir 1 item parmi 100... tu t'amuses pas a afficher une listbox. Bien + rapide pour l'utilisateur de taper les 3 premieres lettres et hop autocompletion, ou meme s'il sen souvient mal juste la 1ere lettre et chercher dans les 5 items de la dropdownlist. Enfin pour moi je ne connait pas + pratique :s

    Sinon concernant ta proposition avec drag drop oué c pas bete mais je suis limité en place sur mon interface: l'item le + long tient dans un combo de 150px de large + je dois faire 2 de ces "grids" sur un flowlayoutpanel de largeur 374. Ce qui ne laisse pas de place pour le 1er grid de gauche (celui ayant tous les items)...

    Mais tu me donne une idée: une checkedListBox dans lequel y aurait tous les items initialement (et leur coût en vis-a-vis). Puis lorsque l'utilisateur "check" 1 item, la list se rafraichirait auto avec les items "trop chers" grisés ?
    Serait-ce trop compliqué a coder ?

    pour ta derniere remarque, en fait c le point de vue utilisateur qui m'importe, pas le point de vue codeur (bien que je sois un débutant ca m'arrangerait lol)
    et aussi pour l'instant je reste en winForms pour apprendre, parce que le WPF a ce que j'ai lu n'a plus rien a voir...

  4. #4
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2009
    Messages
    1 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 1 048
    Points : 2 201
    Points
    2 201
    Par défaut
    Une fonction recherche sur le datagridview avec un textbox c'est pas hyper compliqué non plus....

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bon... j'ai opté pour la solution Listbox + grisage selon valeur de paramètres connus.

    Mais avant de poster le code que j'ai actuellement j'ai un léger problème préliminaire : Comment faire une checkedlistbox à 2 colonnes à partir de 2 champs d'une datatable ?

    Là j'ai fait une simple concaténation
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Private Sub MainWindow_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ...
        For Each Row As DataRow In Me.DataSet.BLUspells
             Me.CheckedListBox1.Items.Add(Row.Item("Names").ToString & " (" & Row.Item("SetPoint").ToString & ")")
        Next
        ...
    End Sub
    Ca marche mais pour la suite c'est pas très pratique. Ce qui m'arrangerait + serait de pouvoir recup directement à partir de la 2e colonne de cette checkedlistbox la valeur de SetPoint. Mais pour cela il me faudrait la syntaxe correcte pour faire une listbox à 2 "vraies" colonnes.
    Je n'ai trouvé aucun exemple ni sur le forum, ni sur MSDN...

    EDIT: je viens d'essayer en LINQ
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim Lvl As Byte = 85
    Me.CheckedListBox1.Items.AddRange(From Row As DataRow In Me.DataSet.BLUspells _
                                      Where CByte(Row.Item("Level")) <= Lvl _
                                      Select {Row.Item("Names"), Row.Item("SetPoint")})
    Erreur de syntaxe: AddRange n'accepte qu'un tableau à 1-dimension...

    EDIT2: 2e essai avec une syntaxe sans erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Me.CheckedListBox1.Items.AddRange(New Object() {From Row As DataRow In Me.DataSet.BLUspells _
                                      Where CByte(Row.Item("Level")) <= Lvl _
                                      Select {Row.Item("Names"), Row.Item("SetPoint")}})
    Mais il ne m'affiche qu'une seule unique ligne "System.Data.EnumerableRowCollection(Of object())"

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonjour,
    et le ListView ne répondrait il pas à tes attentes?
    http://msdn.microsoft.com/fr-fr/libr...VS.100%29.aspx

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bonjour Chris

    Non Listview ne réponds pas a mes attentes, c statique. Enfijn je veux dire autant utiliser une structure + bas "niveau" si on le peut (cf ci dessous).
    et d'autre part, je suis presque sûr que la solution CheckedListbox suffit amplement (j'ai deja vu des listbox multicolonnes sur le web)... si on ne parle pas des pb de syntaxe ...

    Je reviens, faut je passe l'aspirateur sur tous les cheveux arrachés sur ces histoires de syntaxe incorrecte...

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    combobox et checkedlistbox ne permettent pas par défaut de faire du multicolonne, et ne peuvent donc afficher que des strings (via un datamember ou tostring éventuellement)
    sur codeplex (il me semble) il y a un exemple de combobox hérité permettant le multicolonne
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bon k tant pis j'en ai marre je vais faire avec checkedlistbox à "champs concaténés", je poste le reste du code :

    A l'init, la checkedlistbox est vide et le le Label affiche "0"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Private BLUspellsMaxPoints As Byte = 0
     
    Private Sub MainWindow_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Me.BLUspellsTotalSetPoints.Text = "0"
    End Sub
    Puis, j'ai les évenements pouvant déclencher l'apparition de ma checkedlistbox et ses items:
    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
    Private Sub MainJob1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MainJob1.TextChanged
            If Me.MainJob1.Text = "BLU" Then
                For Each Row As DataRow In Me.DataSet.BLUspells
                    If CByte(Row.Item("Level")) <= Me.MainLevel1.Value Then
                        Me.CheckedListBox1.Items.Add(Row.Item("Names").ToString & " (" & Row.Item("SetPoint").ToString & ")")
                    End If
                Next
                BLUspellsMaxPoints = CByte(10 + 5 * Math.Floor((Me.MainLevel1.Value - 1) / 10))
                Me.BLUspellsTotalSetPoints.Text = "0 / " & BLUspellsMaxPoints.ToString
            End If
    End Sub
     
    Private Sub SubJob1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles SubJob1.SelectedIndexChanged
            If Me.SubJob1.Text = "BLU" Then
                For Each Row As DataRow In Me.DataSet.BLUspells
                    If CByte(Row.Item("Level")) <= SubLevel1.Value Then
                        Me.CheckedListBox1.Items.Add(Row.Item("Names").ToString & " (" & Row.Item("SetPoint").ToString & ")")
                    End If
                Next
                BLUspellsMaxPoints = CByte(10 + 5 * Math.Floor((Me.SubLevel1.Value - 1) / 10))
                Me.BLUspellsTotalSetPoints.Text = "0 / " & BLUspellsMaxPoints.ToString
            End If
    End Sub
     
    Private Sub MainLevel1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MainLevel1.ValueChanged
            If Me.MainJob1.Text = "BLU" Then
                For Each Row As DataRow In Me.DataSet.BLUspells
                    If CByte(Row.Item("Level")) <= MainLevel1.Value Then
                        Me.CheckedListBox1.Items.Add(Row.Item("Names").ToString & " (" & Row.Item("SetPoint").ToString & ")")
                    End If
                Next
                BLUspellsMaxPoints = CByte(10 + 5 * Math.Floor((Me.MainLevel1.Value - 1) / 10))
                Me.BLUspellsTotalSetPoints.Text = "0 / " & BLUspellsMaxPoints.ToString
            End If
    End Sub
     
    Private Sub SubLevel1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SubLevel1.ValueChanged
            If Me.SubJob1.Text = "BLU" Then
                For Each Row As DataRow In Me.DataSet.BLUspells
                    If CByte(Row.Item("Level")) <= SubLevel1.Value Then
                        Me.CheckedListBox1.Items.Add(Row.Item("Names").ToString & " (" & Row.Item("SetPoint").ToString & ")")
                    End If
                Next
                BLUspellsMaxPoints = CByte(10 + 5 * Math.Floor((Me.SubLevel1.Value - 1) / 10))
                Me.BLUspellsTotalSetPoints.Text = "0 / " & BLUspellsMaxPoints.ToString
            End If
    End Sub
    Et enfin le fameux code gérant dynamiquement le contenu de ma checkedlistbox :
    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
    Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
            Dim CheckedItemsTotalPoints As Byte = 0
            With Me.CheckedListBox1
                For Each Item As String In .CheckedItems
                    CheckedItemsTotalPoints += CByte(Item.Substring(Item.Length - 2, 1))
                Next
                Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
     
                Dim Diff As Byte = BLUspellsMaxPoints - CheckedItemsTotalPoints
                If Diff > 5 Then : Exit Sub 'Highest SetPoint cost being = 5, nothing else to do
                Else
                    For Each Item As String In .Items
                        If Not .CheckedItems.Contains(Item) _
                        AndAlso CByte(Item.Substring(Item.Length - 2, 1)) >= Diff Then
                            .SetItemCheckState(.Items.IndexOf(Item), CheckState.Indeterminate) 'Item with too high cost becomes uncheckable
                        End If
                    Next
                End If
            End With
    End Sub
    Cela fonctionne à une exception près, très bizarre d'ailleurs: la collection CheckedItems de la checkedListbox reste vide au 1er item coché... Ce qui fait que si je recoche le même item (et donc il devient décoché) ben la fonction me compte cet item quand même... il y a un bug ?

    Sinon, la checkedlistbox affichée n'est pas très jolie, j'aurais préféré voir les SetPoints alignés à droite de chaque item, c'est pour cela j'essayait de faire une checkedlistbox à 2 colonnes. Idem au niveau du code: les setpoints dans leur colonne dédiée m'aurait évité de faire un bidouillage avec substring...

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Bon je crois j'ai compris d'où vient le "bug" du 1er item coché pas pris en compte dans collection CheckedItems lors de l'évenement ItemCheck.

    En fait cet évenement ne s'active pas juste quand l'utilisateur coche une case, mais aussi quand il décoche ou quand l'application "grise" un item. Autrement dit, ItemCheck = changement d'état d'un item (propriété checkstate).
    Résultat dans le code posté précédent qui utilise checkeditems comme collection de base pour les boucles, alors que l'item qui vient d'etre coché (ou décoché) n'etait pas encore dans (ou sorti) de CheckedItems, ben du coup toute la fonction avait 1 action de l'utilisateur de retard.

    J'ai donc refait la procédure ItemCheck
    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
        Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
            With Me.CheckedListBox1
                Dim c As Byte = CByte(.Items(e.Index).ToString.Substring(.Items(e.Index).ToString.Length - 2, 1))
                If e.NewValue = CheckState.Checked Then
                    CheckedItemsTotalPoints += c
                ElseIf e.NewValue = CheckState.Unchecked Then
                    CheckedItemsTotalPoints -= c
                End If
                Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
                Dim Diff As Byte = BLUspellsMaxPoints - CheckedItemsTotalPoints
                If Diff > 5 Then : Exit Sub 'Highest SetPoint cost being = 5, nothing else to do
                Else
                    For x As Integer = 0 To .Items.Count - 1
                        If .GetItemCheckState(x) = CheckState.Unchecked _
                        AndAlso CByte(.Items(x).ToString.Substring(.Items(x).ToString.Length - 2, 1)) >= Diff Then
                            .SetItemCheckState(x, CheckState.Indeterminate) 'Item with too high cost becomes uncheckable
                        End If
                    Next
                End If
            End With
        End Sub
    Là ca fonctionne bien selon que l'utilisateur coche ou décoche un item....jusqu'à déclencher une Exception StackOverflow
    Je n'ai absolument aucune idée d'où ca sort o.O encore heureux que mon ordi n'est pas planté avec

    Quelqu'un pourrait-il m'aider à trouver qu'est ce qui provoque cette boucle infinie ? svp

  11. #11
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    la boucle infinie tu peux la trouver en debug
    tu mets un point d'arret sur l'évènement et au 2ème passage tu regardes la piles des appels


    question qui n'a rien à voir, tu fais ca dans un cadre personnel ou professionnel ?
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  12. #12
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Ok merci Pol63 grâce au debug en effet j'ai trouvé ce qui provoquait la boucle infinie: la méthode .SetItemCheckState. Elle change l'état d'activation de certains items et du coup "rappelle" la fonction ItemCheck a chaque tour de boucle, se rappelant donc elle-même...

    J'ai donc rajouté le fameux flag IsInitialized que Tomlev m'avait conseillé dans un précédent topic, "libérant" la fonction uniquement quand la boucle est terminée.

    Mais du coup j'ai découvert pire: l'état indeterminate ne veut absolument rien dire je peux encore cocher/décocher des éléments "grisés"...
    encore pire: lorsqu'un item voit son état passer à indeterminate, il devient coché...
    Franchement, je ne comprends pas du tout mais alors pas du tout ce que Krosoft pensait en implementant cet état indeterminate, il ne sert absolument a rien...

    Pour ta derniere question Pol63, la finalité de mon projet actuel est pro (m'initier a VB.net et etre capable de faire une appli "de base") mais je le fais en dehors du boulot avec comme "patron" un ancien projet perso deja réalisé sous Excel, en lui rajoutant des fonctionnalités grâce à aux possibilités de VB. Je fais donc d'1 pierre 2 coups.
    Now puis-je te renvoyer la question: pourquoi la poser ? (tu peux répondre en MP si tu préféres vu que c'est hors sujet)

  13. #13
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    l'état indeterminate sert à dire non défini, car un booléen vaut 0 ou 1 mais un booléen nullable vaut 0,1 ou null
    cet état est nécessaire dans certains cas, par exemple dans le cas ou une valeur par défaut existe mais n'est pas connu et pas affichée, le fait de mettre null permet alors de ne pas overrider le comportement par défaut

    sinon la question hors sujet c'est parce que si t'es pas pressé, wpf est une piste à creuser
    parce que les combobox multicolonnes et les infos multiples à afficher c'est 100x plus simple
    et puis ca réduit la taille du code, tu peux écrire en une ligne qu'une liste affiche seulement les éléments dont la valeur est inférieur à la valeur restante à définir, et sans gérer aucun évènement !
    par contre wpf est totalement différent de windows forms, donc ca fait légèrement repartir à zéro, et il faut bien comprendre le principe pour ne pas coder en wpf comme en windows forms. En wpf il est rare de modifier l'interface depuis le code, au point même que nommer les controles devient inutile (les rendant non appelables depuis le code)
    mais ca nécessite d'avoir du temps et que wpf te soit utile professionnellement, car certaines entreprises préfèrent encore le windows forms ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    MMmmm... tres interessant ton dernier post Pol63.

    A t'entendre, on dirait que que WPF vaut la chandelle de repartir à 0, sous réserve d'avoir du temps (ce qui est mon cas en ce moment) ?
    d'apres ce que tu sous-entends, il permettrait même des choses "pas possible" en winforms ? genre listbox à 2 colonnes de tt a l'heure ?

    Concernant les entreprises qui preferent rester en winforms, je ne pense pas que cela me dérange: celles dans lequel j'ai l'occasion de travailler s'en foute presque, du moment que ce soit "clé en main", càd "je clck sur le .exe. ca sort, c'est simple à paramétrer et paf g mes resultats directs et présentés clairement"

    Mon projet Excel s'adresse à des joueurs, lesquels se comportent exactement comme les entreprises : si c'est trop compliqué ou que ca bug ou que c'est mal présenté, ou encore ca rame etc... l'outil est jeté à la corbeille.
    L'interêt pour moi de "convertir ce projet Excel sous VB.net, c'est qu'il s'agit d'un comparateur d'équipements affichant des résultats chiffrés. On peut très bien l'imaginer a la place un comparateur de devis ou encore de vrais equipements industriels.
    Le gros inconvénient que ce projet rencontre est qu'il "rame", avec des tables directement incluses dans le fichier dont la taille totale est modeste comparé à celles qu'on peut rencontrer au boulot. Il a aussi d'autres inconvenients dus principalement aux limitations d'Excel. Mes tentatives de résoudre ces problèmes avec VBA se sont soldés par un superbe commentaire d'un de mes collegues: "tu savais que les macros marchent pas chez la plupart des entreprises ?" donc me voilà chez VB.net, développable gratis avec VB2010express, capable de me fournir un .exe simple qui marche partout.

    Du coup, si tu me conseilles réellement la voie du WPF, y aurait-il un equivalent du .pdf de P.Lasserre (qui m'a énormement aidé) quelquepart ? Je demande pour avoir une base minimum pour "repartir à 0".

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonjour,
    pour le problème "StackOverflowException", cela provient, à mon avis d'un soucis de portée et d'incrémentation de ton x.
    Il repart toujours à 0 ou il reste sur le 1er item qui correspond à la requête du if provoquant la boucle sans fin.
    A tester :
    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
        Dim CheckedItemsTotalPoints As Integer = 0 'Byte = 0
        Dim x As Integer = 0
        Dim compt As Integer = 0
     
        Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
            With Me.CheckedListBox1
                Dim c As Integer = CInt(.Items(e.Index).ToString.Substring(.Items(e.Index).ToString.Length - 2, 1))
                If e.NewValue = CheckState.Checked Then
                    CheckedItemsTotalPoints += c
                ElseIf e.NewValue = CheckState.Unchecked Then
                    CheckedItemsTotalPoints -= c
                End If
                Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
                Dim Diff As Integer = BLUspellsMaxPoints - CheckedItemsTotalPoints
                If Diff > 5 Then
                    Exit Sub 'Highest SetPoint cost being = 5, nothing else to do
                Else
                    If compt = 1 Then
                        x += 1
                    End If
                    For Me.x = x To .Items.Count - 1
                        If .GetItemCheckState(x) = CheckState.Unchecked _
                        AndAlso CInt(.Items(x).ToString.Substring(.Items(x).ToString.Length - 2, 1)) >= Diff Then
                            compt = 1
                            .SetItemCheckState(x, CheckState.Indeterminate) 'Item with too high cost becomes uncheckable
                        End If
                    Next
                End If
            End With
        End Sub
    Pas propre, mais pour le principe.
    Ensuite idem, on peut toujours jouer avec les indéterminés, pour réellement les désactiver, je n'ai jamais essayé...

  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Merci Chris, mais ce n'est pas la requete du If qui provoque la boucle infinie, c l'instruction .SetItemCheckState(), elle change l'état d'activation. Or cette instruction se trouvant dans une procédure qui gére aussi les états d'activation, rien que le fait d'executer cette méthode 1 fois appelle aussitôt la procédure ItemCheck, laquelle réexecute encore le même code jusqu'a arriver encore a .SetItemCheckState, laquelle provoque de nouveau un evenement ItemCheckEventsArgs, etc... la boucle, elle reste toujours a x=1.
    Pour contourner le probleme Tomlev m'avait proposé de tout simplement mettre un flag
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    If Var = True Then
        Var = False
       ... ton code ...
       Var = True
    End If
    ce qui fait qu'a chaque fois que SetItemCheckState rappelle la procédure ItemCheck, il "se casse la gueule" sur ce flag... et du coup la boucle continue. C'est pas propre mais c simple et radical :/
    J'avais rencontré ce même problème avec .datasource = ou .displaymember = qui provoquent indirectement un evenement TextChanged et/ou SelctedIndexChanged, lequel rappelait encore ces mêmes datasource/displaymember...

    Le vrai problème en fait là c les items dont je mets l'étét à indeterminate: ils deviennent effectivement grisés, mais restent selectionnables... (ils deviennent aussi cochés automatiquement ...). je n'ai pas trouvé de propriété du genre CheckedListBox.Items.SelectionMode ou .CanSelect applicable a un item d'index donné.

    En revanche, Pol63 à l'air de dire qu'en WPF ce genre de chose serait "fingers in the noze" ?

  17. #17
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    wpf c'est le rêve pour tout développeur, la rolls des langages de dev ...
    la seule limite c'est l'imagination
    si tu veux mettre des boutons dans un combobox au lieu des string, ca prend une ligne de code, alors qu'en windows forms il faut déjà réfléchir à comment ca peut se faire
    si tu décides après avoir développé une application que tous les boutons seraient bleus, ca prend là aussi une ligne de code, et en windows forms tu te dis "mince j'aurais du pensé à ca au début pour implémenter ce qu'il faut"

    en wpf il y a le langage du code behind (vb.net ou c#) + le xaml qui permet de décrire l'interface
    les bindings + les templates c'est très efficace
    par exemple tu codes en xaml un template pour dire que la classe [utilisateur] s'affiche avec un cadre qui contient : un label marqué "nom", un textbox à côté qui contient le nom puis un label en dessous marqué "mot de passe" avec à côté un textbox qui contient le mot de passe, et à droite un bouton supprimer qui appelle la sub "supprimer" de la classe utilisateur etc...
    et en vb.net tu écris que dans tel listbox tu veux voir afficher le contenu d'une collection de [utilisateur] (= une ligne de code)
    résultat le listbox contient plein de cadres avec pleins de label textbox ...
    modifier une valeur dans le textbox modifie la valeur de l'instance de [utilisateur] sans taper de code, l'ajout d'une personne dans la collection ajoute automatiquement l'utilisateur dans le listbox, sans taper de code non plus ; et le fait de cliquer sur un bouton supprimer, tu ne le gères pas dans ton form, c'est la sub de la classe utilisateur qui sera appelée
    etc...


    autre exemple ou wpf est utile, en windows forms souvent on se retrouve à dire que si tel combobox vaut telle valeur, on rend tels controles visibles etc...
    ce qui fait qu'au final dans un form, on voit de l'extraction de données, du code métier, du code pour afficher le code métier, du code pour mettre à jour le code métier à partir de l'interface, et du code pour gérer l'interface en fonction de l'interface
    en wpf il y a un fichier en xaml pour décrire l'interface et comment elle réagie, et un fichier en vb.net pour dire ce que tu veux faire avec tes instances. et à coté tu as des fichiers de classes métiers qui contiennent la définition des objets (propriétés, actions possibles ...)
    le code est plus concis, plus clair, il y a moins de risques de créer des bugs en modifiant le code, l'interface est évolutive sans toucher au code qui fait fonctionner les données

    par contre il faut coder orienté objet ...


    http://www.microsoft.com/france/visi...4-21DE8C7C7A5E

    j'ai pas vraiment regardé le contenu de celui là, mais y a des webcasts qui donnent vraiment envie de s'y mettre !
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  18. #18
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2009
    Messages
    140
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2009
    Messages : 140
    Points : 37
    Points
    37
    Par défaut
    Les exemples que tu as cité sont exactement les questions que je me suis posé.
    Sous Excel, c'etait vraiment simplissime (0 ligne de code à part les formules) mais limité en possibilités.
    Là en winforms sans aucune connaissance et j'ai encore du mal avec le concept de classe > Objet > instance (en termes de syntaxe je veux dire), j'ai effectivement l'impression de perdre du temps sur des "bricoles"... Exemple de la listbox à 2 colonnes ci dessus...

    Quant aux histoires de mélanger code présentation/données/métier, j'avais déjà prévu mon coup avec tout le code gérant l'interface uniquement (et ses liaisons avec les données importées) dans Form1.vb.
    Les requetes d'importation des données de mes tables Access se trouvent dans un fichier DataSet.xsd.
    Quant au code métier j'ai pas commencé je pensait mettre mes subs dans un 3e fichier Core.vb qui se servirait des valeurs présentes dans les contrôles de l'interface.

    A 1ere vue, le WPF ressemble pas mal au XML, dont je me suis déjà servi à 2 reprises... je suis juste un peu dérouté (je trouve pas par exemple, pour un contrôle DockPanel WPF, sa propriété Dock ou Location pour le positionner dans la MainWindow de base...) Mais je vais y arriver

    Concernant le topic, ben... je peut pas trop le considérer comme complètement Résolu, honnetement je ne sait pas quoi en faire

    EDIT: merci pour ton lien mais déjà l'interface de la page déchire

  19. #19
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    pour ton problème ici, je n'ai plus trop vraiment envie de réfléchir à des trucs du genre en winforms, surtout lié à des datasets, et vu que je n'adhère pas trop aux combobox et checkedlistbox

    le xaml c'est du xml oui, donc des balises et du contenu

    pour le dockpanel, il sert à dire pour les controles à l'intérieur où ils vont etre dockés, c'est à eux de le renseigner

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <dockpanel>
      <button dockpanel.dock="left"/>
      <button dockpanel.dock="bottom"/>
    </dockpanel>
    pour commencer sur wpf il faut déjà voir les 4 types de panels (grid, canvas, dockpanel, stackpanel)
    ce sont les seuls à pouvoir accueillir plusieurs control, même le window ne peut en accueillir qu'un, donc un de ces 4 là
    après il faut aussi se rendre compte qu'un bouton ne peut contenir qu'une seule chose, donc quand on vient de winforms et qu'on veut mettre du texte et une image on ne comprend pas
    en fait il faut mettre un panel dans le bouton qui lui contiendra le texte et l'image
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    <button>
      <dockpanel>
        <textblock content="Texte du bouton" dockpanel.dock="bottom"/>
        <image source="monimage.jpg" dockpanel.dock="top"/>
      </dockpanel>
    </button>
    après il faut voir la classe collections.objectmodel.observablecollection, qui possèdent des évènements de modification de la collection
    puis les depdendencyproperties ou l'interface componentmodel.inotifypropertychanged, qui permettent de notifier l'interface d'un changement suite à une modification d'une propriété d'une classe
    après il faut voir les DataTemplate qui permettent de définir comment est affiché un classe

    si en plus tu es fainéant et que tu utilises une base de données, tu peux aussi te pencher sur entity framework, tu coches les tables que tu veux utiliser, et ca génère tout le code .net pour gérer les données, il suffit ensuite d'utiliser du linq pour dire ce que tu veux de la base de données
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  20. #20
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    665
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 665
    Points : 1 161
    Points
    1 161
    Par défaut
    Bonsoir,
    Je continue en "winforms" et aimerais comprendre ce qui ne va pas dans ce projet qui me semble déjà bien avancé.
    Et en virant les "flags" dont tu parles, à tester :
    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
       Dim CheckedItemsTotalPoints As Integer = 0
        Dim Diff As Integer = 0
     
        Private Sub CheckedListBox1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles CheckedListBox1.ItemCheck
            With Me.CheckedListBox1
                Dim c As Integer = CInt(.Items(e.Index).ToString.Substring(.Items(e.Index).ToString.Length - 2, 1))
     
                If e.NewValue = CheckState.Checked Then
                    CheckedItemsTotalPoints += c
                    Diff = BLUspellsMaxPoints - CheckedItemsTotalPoints
                    If Diff < 0 Then
                        CheckedItemsTotalPoints -= c
                        e.NewValue = CheckState.Unchecked
                        Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
                        MessageBox.Show("Vous n'avez droit qu'à  " & Diff + c & " points")
                    Else
                        Diff = BLUspellsMaxPoints - CheckedItemsTotalPoints
                        Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
     
                    End If
     
                ElseIf e.NewValue = CheckState.Unchecked Then
                    CheckedItemsTotalPoints -= c
                    Me.BLUspellsTotalSetPoints.Text = CheckedItemsTotalPoints.ToString & " / " & BLUspellsMaxPoints.ToString
     
                End If
     
            End With
        End Sub

Discussions similaires

  1. comment créer une arborescence dynamique
    Par amine84 dans le forum Servlets/JSP
    Réponses: 14
    Dernier message: 22/09/2008, 11h42
  2. Réponses: 2
    Dernier message: 20/07/2008, 19h22
  3. Réponses: 1
    Dernier message: 15/02/2008, 16h55
  4. [RaveReport] Comment créer une page dynamiquement
    Par bullrot dans le forum C++Builder
    Réponses: 1
    Dernier message: 18/12/2007, 16h33
  5. [reports] comment créer une requete dynamiquement
    Par lifeisgood dans le forum Reports
    Réponses: 4
    Dernier message: 31/01/2007, 12h15

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