Domanda

Sto compilando elementi nel mio ComboBox da un file XML usando una DataTable. Attualmente l'ho impostato in modo che una colonna sia il membro di visualizzazione di ComboBox e un'altra sia il suo membro di valore. Tuttavia, ciò potrebbe non funzionare sempre per me, poiché devo impostare il parametro selectedItem e il membro value potrebbe non essere univoco.

Non so se c'è un duplicato del membro del valore nella tabella o no, quindi la mia idea era che avrei inserito l'intero DataRow come membro del valore del ComboBox e quindi avrei usato ComboBox.SelectedITem = (DataRow) some_data_row; per la selezione e selezionerebbe sempre l'oggetto ComboBox giusto.

Come potrei farlo? Esiste un modo migliore per farlo? Sono aperto a suggerimenti, tuttavia è molto importante che sia possibile visualizzare sia il membro di visualizzazione sia il membro di valore.

Grazie per il tuo aiuto!

MODIFICA : Forse non ero abbastanza chiaro prima, tuttavia mentre chiedo se questo è l'approccio migliore qui, sto anche chiedendo a come di farlo. Se non imposto il parametro valuemember, SelectedItem è di tipo DataRowView ... Si noti che desidero utilizzare il parametro selectedValue per selezionare gli elementi da ComboBox e se provo a farlo senza impostare esplicitamente il valore membro viene generata un'eccezione.

È stato utile?

Soluzione 2

Prima di tutto grazie Adam Robinson, sono sicuro che la tua risposta fosse corretta, ma non era proprio quello che volevo sentire. Ho risolto il mio problema in modo diverso e penso che possa essere utile a qualcun altro, quindi lo sto pubblicando qui.

Quello che ho fatto è stato creare una nuova classe, nel mio caso l'ho chiamato ListObject, che aveva una proprietà DataRow (come vedrai in seguito funziona anche per altri tipi, l'ho usato solo perché è quello che volevo davvero come proprietà del valore del mio oggetto). Sovrascrive anche i metodi:

  • String ToString ()
  • bool Equals (object obj)
  • int GetHashCode () - non è necessario nel mio caso, tuttavia Visual Studio
    ti avverte che dovrebbe essere ignorato.

L'idea era che avrei potuto riempire le raccolte ComboBox.Items con oggetti della mia classe, visualizzare una stringa personalizzata (se non l'avessi elaborata in questo modo, la mia prossima domanda su Stack Overflow sarebbe probabilmente quella di personalizzare DisplayMembers durante la lettura elementi da un DataRow) e confronta solo un elemento di classe (nel mio caso DataRow).

Quindi ecco il codice e funziona benissimo (almeno per quello che volevo farne).

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();
    }
}

Nel mio caso funziona benissimo dato che posso semplicemente riempire i ComboBox con un'istruzione foreach:

dtUsers.ReadXml(Program.Settings.xmlInputUsers);

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

E quando ottengo il DataRow che voglio selezionato, faccio semplicemente questo:

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

Dove non devo preoccuparmi di DisplayMember ecc., poiché verranno confrontati solo quelli di DataRow e i parametri di visualizzazione verranno comunque impostati da quando hai compilato la raccolta ComboBox.Items. Inoltre, poiché il metodo toString viene ignorato, puoi davvero personalizzare il tuo output.

La creazione di questa classe è stata possibile solo a causa dell'articolo di msdn su Proprietà ComboBox.SelectedItem in cui è stato notato che la proprietà SelectedItem funziona utilizzando il metodo IndexOf. Questo metodo utilizza il metodo Equals per determinare l'uguaglianza.

Altri suggerimenti

Se associ un ListBox a un DataTable , lo stai effettivamente legando a un DataView che rappresenta quel DataTable ( DataTable implementa IListSource e che restituisce un DataView ). Non puoi impostare direttamente SelectedItem su un'istanza DataRow , devi impostarlo su un'istanza DataRowView . Sfortunatamente non esiste un modo semplice per ottenere un DataRowView da un DataRow .

Faresti meglio a fare tutte le tue interazioni attraverso un DataRowView . Ciò ti consentirà di impostare SelectedItem esplicitamente.

Non puoi usare la proprietà SelectedValue , devi usare SelectedItem per questo.

Questo è il modo più semplice per portare DataTable in una casella combinata

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();

    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top