System.ArgumentException:Complex DataBinding accetta come origine dati un IList o un IListSource

System.ArgumentException:Complex DataBinding accetta come origine dati un IList o un IListSource

Se provi a impostare DataSource di un controllo elenco su un tipo che non può gestire, otterrai la seguente eccezione:

Nota:questo vale per tutti i controlli della sottoclasse ListControl, come ComboBox e ListBox.

Ciò crea confusione perché la proprietà DataSource è di tipo oggetto , ma può essere impostato solo su IList o IListSource. È un tipo non sicuro, perché impone questo vincolo di tipo in fase di esecuzione.

Per risolvere il problema, converti l'oggetto origine dati in un elenco con .ToList() o utilizza BindingSource. Mostrerò degli esempi di seguito.

Soluzione – Usa .ToList()

Supponiamo di voler utilizzare le chiavi di un dizionario come origine dati.

Non puoi semplicemente impostare DataSource =dictionary.Keys, perché KeyCollection non implementa IList / IListSource.

Invece, puoi convertire le chiavi in ​​un elenco chiamando .ToList():

var map = new Dictionary<string, string>()
{
	["a"] = "b"
};

cbVehicleTypes.DataSource = map.Keys.ToList();
Code language: C# (cs)

Lo stesso problema si verifica quando si tenta di utilizzare una query Linq come origine dati, poiché una query Linq restituisce un IEnumerable. Per usarlo come origine dati, devi chiamare .ToList(), in questo modo:

cbVehicleTypes.DataSource = map.Keys.Where(t => t.Length > 1).ToList();
Code language: C# (cs)

Soluzione:utilizza BindingSource

Quando non puoi impostare direttamente il tuo oggetto come origine dati e non vuoi (o non puoi) convertirlo in un elenco, puoi invece utilizzare un BindingSource.

Ad esempio, per utilizzare le chiavi di un dizionario come origine dati, puoi utilizzare BindingSource con il dizionario in questo modo:

var map = new Dictionary<string, string>()
{
	["a"] = "b"
};

cbVehicleTypes.DataSource = new BindingSource(map, "Key");
Code language: C# (cs)

Questo non funziona bene con le query Linq. Funziona bene se la query restituisce qualcosa, ma se la tua query Linq non restituisce nulla, il controllo mostrerà qualcosa di strano, come System.Linq.Enumerable+WhereEnumerableIterator`1[System.String] .

Attenersi a .ToList() se si utilizza una query Linq come origine dati per evitare di doverla occupare.