2012-04-24 7 views
4

DropDownlistまたはRepeaterにデータバインドできるDataTableを返す関数があります。しかし、DataTableのDataRowsのIEnumerableをデータバインドすると、HttpExceptionが発生します。 "DataBinding: 'System.Data.DataRow'に 'some_column'という名前のプロパティが含まれていません。DataRowsのIEnumerableをデータバインドできませんか? HttpException?

repeater.DataSource = ThisReturnsDataTable(); // Works fine 
repeater.DataSource = ThisReturnsDataTable.AsEnumerable(); // HttpException 

なぜですか?

私は例えばのように、問題の解決策を探していないよ。私は単にでDataRowのIEnumerableを持つデータバインディングが失敗した理由を知りたい

repeater.DataSource = ThisReturnsDataTable().AsEnumerable().Select(
    x => new {some_column = x["some_column"]}); 

答えて

11

彼の最初の問題解決策はAsDataView()ですが、(少なくとも3.5では)動作しているとは思われませんでしたが、かなり良い説明が見つかりましたhereです。しかし、CopyToDataTable()はうまく動作します。

.Netデータテーブルは、データ駆動型の アプリケーションを作成するときに非常に便利です。しかし、テーブルには データローの任意のリストにグリッド(または他のコントロール)をバインドするための明白な方法はありません。 DataSourceをDataTable自体に設定することで、テーブル全体に直接バインドできます。また、フィルタ付きのDataViewを作成して、テーブルのサブセット にバインドできます。

一般に、IEnumerable(たとえば、LINQクエリ)にバインドすることはできません。 データバインディングインフラストラクチャは、IList(非汎用) またはIListSourceのみを処理できます。これは、あらゆる種類のデータソースに当てはまります。 したがって、任意のLINQクエリにバインドするには、.ToList()を呼び出す必要があります。 (または .ToArray())

ただし、DataTableにバインドする場合は、 リストも使用できません。試してみると、4つの列(RowError、 RowState、Table、およびHasErrors)があり、有用な情報は得られません。この は、リストがDataRowsの特別なプロパティについてデータバインディング インフラストラクチャに通知しないために発生します。 に問題を理解するには、背景が必要です

データバインディングはListBindingHelperおよびTypeDescriptor クラスによって制御されます。リストにバインドすると、 ListBindingHelper.GetListItemPropertiesメソッドが呼び出され、リスト内の 列が取得されます。リストがITypedListインターフェイスを実装している場合は、 GetItemPropertiesメソッドが呼び出されます。それ以外の場合は、 TypeDescriptorを使用して、リスト内の最初の項目のプロパティを取得します。 (これは、リフレクションを使用)(データテーブルも IListSourceを用いて、スルー結合)ITypedListを実装し、テーブルの列を露出 DataColumnPropertyDescriptorsを返し

データビュークラス。 これは、DataViewまたはDataTableにバインドして列を表示できる理由です。 ただし、Listにバインドすると、 がプロパティとして列を返すことができるITypedListはありません。したがって、それは 反射に戻り、DataRowクラスの物理的特性を示します。

この問題を解決するには、 のITypedList実装を利用できるように、DataViewでリストをラップする必要があります。 AsyncView()メソッドを使用して とすることができます。このメソッドは、DataTableクラスとEnumerableRowCollectionクラスの でのみ使用できます。任意のLINQクエリで を呼び出すことはできません。特別なバージョンのCast、 OrderBy、Where、およびSelectメソッドをDataTableから呼び出すことによって、 EnumerableRowCollectionのみを取得できます。

したがって、クエリで AsDataView()を呼び出すことによって、単純なLINQクエリにデータバインドすることができます。 AsEnumerable()の呼び出しは、型付きデータセットには必要ありません

List<DataRow> list = ...; 
    grid.DataSource = datatable.AsEnumerable() 
        .Where(list.Contains) 
        .AsDataView(); 

:リストに、以上の 複雑なクエリにバインドするには、醜いハックを使用することができます。

CopyToDataTable()を呼び出すこともできます。 IEnumerableでは[sic]が動作します。ただし、行のディープコピーを作成するので、 ユーザーにデータを更新させたい場合、または の場合、元のdatarowsに加えられた変更をユーザーに表示させたい場合は役に立ちません。

から:http://blog.slaks.net/2011/01/binding-to-lists-of-datarows.html

0

私が間違っているかもしれないが、私の代わりに.Where句を行うので、あなたはこのような何かを行うことができるはずと信じて:

DirectCast([datatable].AsEnumerable, EnumerableRowCollection(Of DataRow)).AsDataView() 
関連する問題