2012-04-24 66 views
4

我有一個函數返回一個DataTable,我可以綁定到DropDownlist或Repeater就好了。但是,如果我databind IEnumerable的DataTable的DataRows,我得到一個HttpException:「DataBinding:'System.Data.DataRow'不包含屬性的名稱'some_column'」。無法數據綁定IEnumerable的DataRows? HttpException?

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

這是爲什麼?

我不是尋找一個解決問題的辦法,例如像:

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

我只是想知道爲什麼有數據行的IEnumerable的數據綁定失敗。

回答

11

我發現了一個很好的解釋here,儘管他對問題的第一個解決方案AsDataView()似乎沒有工作/存在(至少在3.5中)。儘管如此,CopyToDataTable()仍然可以運作。

。當編寫數據驅動的 應用程序時,Net DataTable可能非常有用。但是,它們有一個侷限性:沒有明顯的方式將表格(或其他控件)數據綁定到任意數據行的列表 。您可以通過將數據源設置爲DataTable本身直接綁定到整個表,並且可以通過創建帶有過濾器的DataView綁定到表的子集。

通常,您不能綁定到IEnumerable(例如,LINQ查詢); 數據綁定基礎架構只能處理IList(非通用) 或IListSource。對於任何類型的數據源都是如此。 因此,要綁定到任何LINQ查詢,您需要調用.ToList()。 (或 .ToArray())

但是,綁定到DataTable時,甚至不能使用 列表。如果你嘗試,你會得到四列(RowError, RowState,Table和HasErrors),並沒有有用的信息。發生這個 是因爲List沒有告訴關於DataRows的特殊屬性的數據綁定 基礎結構。要知道 的問題,需要一些背景知識

數據綁定是由ListBindingHelper和TypeDescriptor類控制的。當綁定到列表時,將調用ListBindingHelper.GetListItemProperties方法來獲取列表中的 列。如果該列表實現ITypedList接口,則調用其GetItemProperties方法。否則,它將使用 TypeDescriptor獲取列表中第一項的屬性。 (此使用反射)

DataView類(其數據表也通過結合使用 IListSource)實現ITypedList並返回 DataColumnPropertyDescriptors暴露在表中的列。 這就是爲什麼你可以綁定到DataView或DataTable並查看列。 但是,當您綁定到列表時,不會有ITypedList可以將列作爲屬性返回。因此它會回退 反射並顯示DataRow類的物理屬性。

要解決此問題,您需要將列表包裝在DataView中,以便您可以利用其ITypedList實現。您可以使用AsDataView()方法執行 。此方法僅在DataTable和EnumerableRowCollection類的 上可用;它不能被 調用任意的LINQ查詢。您只能通過調用特殊版本的Cast, OrderBy,Where和Select方法從DataTable獲得EnumerableRowCollection。

因此,您可以通過在查詢中調用 AsDataView()來將數據綁定到簡單的LINQ查詢。綁定到一個列表,或更復雜的 查詢,你可以使用一個醜陋的黑客:是不是需要類型化數據集

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

的AsEnumerable()調用。

您也可以調用CopyToDataTable(),它將在任意的IEnumerable上調用[sic]任意的 。但是,它會對行進行深層複製,因此如果您希望用戶更新數據,或者您希望用戶查看(在代碼中)對原始數據行進行的更改,則無關緊要。

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

0

我可能是錯的,但我相信,而不是做.Where條款,你應該能夠做這樣的事情:

DirectCast([datatable].AsEnumerable, EnumerableRowCollection(Of DataRow)).AsDataView()