System.ArgumentException:複雑な DataBinding はデータ ソースとして IList または IListSource を受け入れます

リスト コントロールの DataSource を処理できないタイプに設定しようとすると、次の例外が発生します:

注:これは、ComboBox や ListBox など、ListControl をサブクラス化するすべてのコントロールに適用されます。

DataSource プロパティが object 型であるため、これは紛らわしいです 、ただし、IList または IListSource にのみ設定できます。実行時にこの型の制約を強制するため、型は安全ではありません。

この問題を解決するには、.ToList() を使用してデータ ソース オブジェクトをリストに変換するか、BindingSource を使用します。以下に例を示します。

解決策 – .ToList() を使用

辞書のキーをデータ ソースとして使用するとします。

KeyCollection は IList / IListSource を実装していないため、単に DataSource =dictionary.Keys を設定することはできません。

代わりに、.ToList() を呼び出してキーをリストに変換できます:

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

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

Linq クエリは IEnumerable を返すため、Linq クエリをデータ ソースとして使用しようとすると、同じ問題が発生します。これをデータ ソースとして使用するには、次のように .ToList() を呼び出す必要があります。

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

解決策 – BindingSource を使用する

オブジェクトをデータ ソースとして直接設定できず、リストに変換したくない (または変換できない) 場合は、代わりに BindingSource を使用できます。

たとえば、辞書のキーをデータ ソースとして使用するには、次のように BindingSource を辞書と共に使用できます。

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

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

これは、Linq クエリではうまく機能しません。クエリが何かを返す場合は問題なく動作しますが、Linq クエリが何も返さない場合、コントロールは System.Linq.Enumerable+WhereEnumerableIterator`1[System.String] のように奇妙なものを表示します。 .

これに対処する必要がないように、Linq クエリをデータ ソースとして使用している場合は、.ToList() を使用してください。