Question

Je remplis les éléments de ma ComboBox à partir d'un fichier XML à l'aide d'un DataTable. Actuellement, je l'ai défini de sorte qu'une colonne soit le membre d'affichage de ComboBox et une autre, sa valeur. Toutefois, cela risque de ne pas toujours fonctionner pour moi, car je dois définir le paramètre selectedItem et la valeur member peut ne pas être unique.

Je ne sais pas s'il existe ou non un doublon du membre value dans la table. Mon idée était donc de placer DataRow entier en tant que membre value du ComboBox, puis d'utiliser ComboBox.SelectedITem = (DataRow) some_data_row; pour sélectionner et sélectionnerait toujours le bon objet ComboBox.

Comment pourrais-je accomplir cela? Existe-t-il une meilleure façon de le faire? Je suis ouvert aux suggestions, mais il est très important de pouvoir accéder à la fois aux membres d'affichage et aux membres de valeur.

Merci pour votre aide!

MODIFIER : Je n’étais peut-être pas assez clair auparavant. Cependant, même si je demande si c’est la meilleure approche, je demande également à comment comment procéder. Si je ne définit pas le paramètre valuemember, l'élément SelectedItem est de type DataRowView ... Veuillez noter que je souhaite utiliser le paramètre selectedValue pour sélectionner des éléments dans ComboBox, et si j'essaie de le faire sans définir explicitement la valeur member membre une exception est levée.

Était-ce utile?

La solution 2

Tout d'abord merci Adam Robinson, je suis sûr que votre réponse était correcte, mais ce n'était tout simplement pas ce que je voulais entendre. J'ai résolu mon problème d'une manière différente et je pense qu'il peut être utile à quelqu'un d'autre, je le poste donc ici.

Ce que j’ai fait, c’est que j’ai créé une nouvelle classe; dans mon cas, je l’ai nommée ListObject, qui possédait une propriété DataRow (comme vous le verrez plus tard, cela fonctionne aussi pour d’autres types, c’est ce que j’ai voulu faire. comme ma propriété de valeur d'article). Il remplace également les méthodes:

  • Chaîne ToString ()
  • bool Equals (object obj)
  • int GetHashCode () - n'est pas nécessaire dans mon cas, cependant, Visual Studio

    vous avertit qu'il devrait être remplacé.

L’idée était de pouvoir remplir les collections ComboBox.Items avec des objets de ma propre classe et d’afficher une chaîne personnalisée (si je n’avais pas travaillé de la sorte, ma prochaine question sur le débordement de pile concernerait probablement la personnalisation de DisplayMembers lors de la lecture. éléments d'un DataRow) et ne compare qu'un élément d'une classe (dans mon cas, DataRow).

Voici donc le code et cela fonctionne très bien (du moins pour ce que je voulais en faire).

public class ListObject
{
    public DataRow element;

    public String DisplayObject = null;

    public ListObject(DataRow dr)
    {
        element = dr;
    }

    public ListObject(DataRow dr, String dspObject)
    {
        element = dr;
        DisplayObject = dspObject;
    }

    public override String ToString()
    {
        if (DisplayObject == null) throw new Exception("DisplayObject property was not set.");

        return element[DisplayObject].ToString();
    }

    public override bool Equals(object obj)
    {
        if (obj.GetType() == typeof(ListObject))
            return Equals(((ListObject)obj).element, this.element);
        else return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

Dans mon cas, cela fonctionne très bien car je peux simplement remplir la ComboBox avec une déclaration foreach:

dtUsers.ReadXml(Program.Settings.xmlInputUsers);

foreach(DataRow dr in dtUsers.Rows) 
{
    cmbUser.Items.Add(new ListObject(dr, "Name"));
}

Et quand je récupère le DataRow que je veux, je fais juste ceci:

cmbUser.SelectedItem = new ListObject(dlg.SelectedDataRow);

Où je n'ai pas à me soucier de DisplayMember, etc., car seuls les DataRow seront comparés et vos paramètres d'affichage seront toujours définis à partir du moment où vous avez rempli la collection ComboBox.Items. De plus, puisque la méthode toString est remplacée, vous pouvez vraiment personnaliser votre sortie.

La création de cette classe n’a été possible que grâce à l’article msdn sur Propriété ComboBox.SelectedItem dans lequel il a été noté que cette propriété SelectedItem fonctionne à l’aide de la méthode IndexOf. Cette méthode utilise la méthode Equals pour déterminer l'égalité.

Autres conseils

Si vous liez un ListBox à un DataTable , vous le liez en fait à un DataView qui représente ce DataTable ( DataTable implémente IListSource et renvoie un DataView ). Vous ne pouvez pas définir directement SelectedItem sur une instance DataRow , vous devez le définir sur une instance DataRowView . Malheureusement, il n'existe pas de moyen facile d'obtenir un DataRowView à partir d'un DataRow .

Vous feriez mieux de faire toutes vos interactions avec un DataRowView . Cela vous permettra de définir SelectedItem explicitement.

Vous ne pouvez pas utiliser la propriété SelectedValue , vous devez utiliser SelectedItem pour cela.

C’est le moyen le plus simple d’obtenir DataTable dans une liste déroulante

private void load() { 
DataTable dt = // get data from DB 
comboBox1.ValueMember = null; // allows you to get all fields in the obj to combobox
comboBox1.DisplayMember = "ccType";//label displayed from dt
comboBox1.DataSource = dt;
}
//to test 
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {

        DataRowView current = (DataRowView)comboBox1.SelectedValue;
        string drs = current.Row["ID"].ToString();

    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top