none
Liste multi-champs RRS feed

  • Question

  • Bonjour tout le monde,

    Dans WinForms, on peut facilement attacher à une ListBox une liste d'objets, ce qui permet ensuite d'accéder à leurs différents champs sans qu'il y ait besoin qu'ils soient affichés, ou liés à SelectValue.

    Dans WebForms j'ai essayé de faire pareil, ayant vu une propriété ItemType, mais je me suis vu opposer une exception d'impossibilité de convertir ListItem dans le type que j'avais choisi.

    Y a-t-il des considérations particulières que j'aie oublié de prendre en compte ?

    samedi 5 mars 2022 13:44

Réponses

  • Bonjour,

    ListBox n'est pas adapté à cet usage, GridView s'en sortira mieux.

    On peut souhaiter ne pas afficher les colonnes d'identifiants, toutefois Visible=false ne conviendra pas, car comme il n'y aura pas de rendu on  ne sera pas en mesure de lire le contenu.

    Plutôt un style évitant l'affichage :

    protected void GridView1_PreRender(object sender, EventArgs e)
    {
        foreach(GridViewRow R in GridView1.Rows)
        {
            R.Cells[1].Style.Add("display", "none");
            R.Cells[2].Style.Add("display", "none");
        }
    }
    

    (Les colonnes de données sont numérotées à partir de 1 car j'ai ajouté une colonne 0 pour le contrôle qui déclenche la sélection de la ligne.)

    Attention que ceci ne traite pas la ligne de titre, si on n'y prend garde cela peut introduire un décalage.

    Avec ceci on pourra facilement lire les champs d'identifiants :

    protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        GridViewRow R = GridView1.SelectedRow;
        int idTracteur = int.Parse(R.Cells[1].Text);
        int idEquipement = int.Parse(R.Cells[2].Text);
    }
    

    En gardant la même requête j'ai réalisé l'adaptation rapidement, toutefois le contrôle GridView permet d'afficher une colonne pour l'intitulé de tracteur et une pour l'intitulé d'équipement, ce qui aura l'avantage de donner quelque chose de plus lisible qu'en les séparant simplement par un point-virgule.


    • Marqué comme réponse Gloops vendredi 18 mars 2022 16:03
    • Modifié Gloops vendredi 18 mars 2022 16:13
    vendredi 18 mars 2022 16:02

Toutes les réponses

  • Bonjour,

    La documentation suivante pourrait peut-être vous aider: ListBox Classe.


    Cordialement,
    Nina

    Microsoft propose ce service gratuitement, dans le but d'aider les utilisateurs et d'élargir les connaissances générales liées aux produits et technologies Microsoft. Ce contenu est fourni "tel quel" et il n'implique aucune responsabilité de la part de Microsoft.

    lundi 7 mars 2022 10:45
    Modérateur
  • Bonjour,

    En y cherchant "colonne", je tombe sur

     FindFieldTemplate(Control, String)
    	
    
    Retourne le modèle de champ pour la colonne spécifiée dans le conteneur d'attribution de noms du contrôle spécifié.

    ce qui, vraisemblablement, laisse entendre que j'ai raison de m'interroger.

    Je me rends compte que pour aller plus loin il faudra que je fournisse quelques éléments pour qu'on ait une chance de voir où j'ai commis une erreur.

    lundi 7 mars 2022 16:58
  • Bonjour,

    Pour rappel, j'ai cherché à initialiser une ListBox avec des données d'un type donné ("type métier") comme on fait sous WinForms, et sur une page WebForms je n'étais pas aussi à l'aise avec ça.

    Il nous fallait un exemple pour mieux situer le problème, alors je m'y suis attelé.

    Nous avons une table de tracteurs :

    tabTracteurs

    ainsi qu'une table d'équipements :

    tabEquipements

    En préparation d'une compétition nous allons vouloir savoir quels tracteurs portent quels équipements.

    À cet effet nous disposons d'une table AssoEquip dont chaque enregistrement porte deux champs, idTracteur, idEquipement.

    Il n'aura échappé à personne que le shéma est le même que pour la gestion des utilisateurs et des rôles pour Asp.Net, mais avec des problèmes de verrouillage en moins.

    Sur une page WebForms j'ai créé deux ListBoxes lbxTracteurs et lbxEquipements. La gestion est ici simplifiée puisque les listes peuvent être associées aux tables.

    Une fois que dans les listes j'ai sélectionné un tracteur et un équipement, un bouton me permet de les associer (en toute rigueur je devais lui ajouter le contrôle des doublons) :

            protected void btnAjout_Click(object sender, EventArgs e)
            {
                lblTracteur.Text = lbxTracteurs.SelectedItem.Text;
                lblEquipement.Text = lbxEquipements.SelectedItem.Text;
                using(SqlConnection conn = new SqlConnection(SqlDataSourceTracteurs.ConnectionString))
                {
                    conn.Open();
                    SqlCommand cmd = new SqlCommand("INSERT INTO AssoEquip(IdTracteur, IdEquipement) "
                                            + "Values(@tracteur, @equip)", conn);
                    cmd.Parameters.AddWithValue("tracteur", lbxTracteurs.SelectedValue);
                    cmd.Parameters.AddWithValue("equip", lbxEquipements.SelectedValue);
                    cmd.ExecuteNonQuery();
                    conn.Close();
                }
                lbxAssoEquip.DataBind();
            }

    À droite de ce bouton, une liste lbxAssoEquip permet de visualiser ces associations.

    Elle est initialisée avec cette requête :

    SELECT Tracteurs.Id AS IdTracteur,

    Equipement.Id AS IdEquipement,

    Tracteurs.NomTracteur + ';' + Equipement.NomEquipement AS Intitule

    FROM Tracteurs

    INNER JOIN AssoEquip

    ON Tracteurs.Id = AssoEquip.IdTracteur

    INNER JOIN Equipement

    ON AssoEquip.IdEquipement = Equipement.Id


    Jusque là, tout se passe très bien.

    Maintenant, je voudrais créer un autre bouton pour supprimer l'association sélectionnée dans la troisième liste. C'est là que ça se gâte.

    Pour l'enregistrement sélectionné (SelectedItem) je voudrais extraire les champs idTracteur et idEquipement, pour pouvoir supprimer de la table AssoEquip l'enregistrement qui comporte ces deux valeurs.

    J'ai créé une classe  :

        public class DisplayAsso
        {
            public int IdEquipement { get; set; }
            public int IdTracteur { get; set; }
            public string Intitule { get; set; }
        }

    et je voudrais faire un "cast"

    ((DisplayAsso)lbxAssoEquip.SelectedItem)

    de façon à pouvoir, derrière, appeler les propriétés idTracteur et idEquipement.

    Or, je me heurte à une erreur de cast invalide. Pourtant, dans la propriété ItemType de lbxAssoEquip, j'ai écrit DisplayAsso.

    Mais que je prenne cette précaution ou pas, l'erreur est la même.

    Aurais-je oublié quelque chose de tout simple ?

    Je peux m'en sortir en créant un tableau DisplayAsso[] où je mets les mêmes valeurs que dans la liste, pour pouvoir exploiter SelectedIndex. Mais j'imagine que nous sommes d'accord que ce n'est pas du travail propre.



    • Modifié Gloops mardi 15 mars 2022 18:07
    mardi 15 mars 2022 17:05
  • Bonjour,

    ListBox n'est pas adapté à cet usage, GridView s'en sortira mieux.

    On peut souhaiter ne pas afficher les colonnes d'identifiants, toutefois Visible=false ne conviendra pas, car comme il n'y aura pas de rendu on  ne sera pas en mesure de lire le contenu.

    Plutôt un style évitant l'affichage :

    protected void GridView1_PreRender(object sender, EventArgs e)
    {
        foreach(GridViewRow R in GridView1.Rows)
        {
            R.Cells[1].Style.Add("display", "none");
            R.Cells[2].Style.Add("display", "none");
        }
    }
    

    (Les colonnes de données sont numérotées à partir de 1 car j'ai ajouté une colonne 0 pour le contrôle qui déclenche la sélection de la ligne.)

    Attention que ceci ne traite pas la ligne de titre, si on n'y prend garde cela peut introduire un décalage.

    Avec ceci on pourra facilement lire les champs d'identifiants :

    protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {
        GridViewRow R = GridView1.SelectedRow;
        int idTracteur = int.Parse(R.Cells[1].Text);
        int idEquipement = int.Parse(R.Cells[2].Text);
    }
    

    En gardant la même requête j'ai réalisé l'adaptation rapidement, toutefois le contrôle GridView permet d'afficher une colonne pour l'intitulé de tracteur et une pour l'intitulé d'équipement, ce qui aura l'avantage de donner quelque chose de plus lisible qu'en les séparant simplement par un point-virgule.


    • Marqué comme réponse Gloops vendredi 18 mars 2022 16:03
    • Modifié Gloops vendredi 18 mars 2022 16:13
    vendredi 18 mars 2022 16:02