无法数据绑定IEnumerable的DataRows?HttpException?

Pro*_*one 4 asp.net data-binding ienumerable

我有一个函数返回一个DataTable,我可以将其数据绑定到DropDownlist或Repeater就好了.但是,如果我数据绑定DataTable的DataRows的IEnumerable,我会得到一个HttpException:"DataBinding:'System.Data.DataRow'不包含名为'some_column'的属性".

repeater.DataSource = ThisReturnsDataTable();  // Works fine
repeater.DataSource = ThisReturnsDataTable.AsEnumerable();  // HttpException
Run Code Online (Sandbox Code Playgroud)

为什么是这样?

我不是在寻找问题的解决方案,例如:

repeater.DataSource = ThisReturnsDataTable().AsEnumerable().Select(
    x => new {some_column = x["some_column"]});
Run Code Online (Sandbox Code Playgroud)

我只是想知道为什么与IEnumerable DataRows的数据绑定失败.

Pro*_*one 11

我在这里找到了一个很好的解释,虽然他对问题的第一个解决方案AsDataView(),似乎没有工作/存在(至少在3.5中).CopyToDataTable()但是,游泳工作.

在编写数据驱动的应用程序时,.Net DataTables非常有用.但是,它们有一个限制:没有明显的方法将网格(或其他控件)数据绑定到表中的任意数据行列表.您可以通过将DataSource设置为DataTable本身来直接绑定到整个表,并且可以通过使用过滤器创建DataView来绑定到表的子集.

通常,您不能绑定到IEnumerable(例如,LINQ查询); 数据绑定基础结构只能处理IList(非泛型)或IListSource.对于任何类型的数据源都是如此.因此,要绑定到任何LINQ查询,需要调用.ToList().(或.ToArray())

但是,绑定到DataTable时,甚至无法使用List.如果您尝试,您将获得四列(RowError,RowState,Table和HasErrors)并且没有有用的信息.发生这种情况是因为List没有告诉数据绑定基础结构有关DataRows的特殊属性.要理解这个问题,一些背景是必要的

数据绑定由ListBindingHelper和TypeDescriptor类控制.绑定到列表时,将调用ListBindingHelper.GetListItemProperties方法以获取列表中的列.如果列表实现了ITypedList接口,则调用其GetItemProperties方法.否则,它将使用TypeDescriptor获取列表中第一个项的属性.(这使用反射)

DataView类(DataTable也使用IListSource绑定)实现ITypedList并返回公开表中列的DataColumnPropertyDescriptors.这就是您可以绑定到DataView或DataTable并查看列的原因.但是,绑定到List时,没有可以将列作为属性返回的ITypedList.因此它依赖于反射并显示DataRow类的物理属性.

要解决此问题,您需要将列表包装在DataView中,以便您可以利用其ITypedList实现.您可以使用AsDataView()方法执行此操作.此方法仅适用于DataTable和EnumerableRowCollection类; 它不能在任意LINQ查询上调用.您只能通过从DataTable调用Cast,OrderBy,Where和Select方法的特殊版本来获取EnumerableRowCollection.

因此,您可以通过在查询上调用AsDataView()来数据绑定到简单的LINQ查询.要绑定到List或更复杂的查询,您可以使用丑陋的黑客:

    List<DataRow> list = ...; 
    grid.DataSource = datatable.AsEnumerable()
                   .Where(list.Contains)
                   .AsDataView();
Run Code Online (Sandbox Code Playgroud)

类型化数据集不需要AsEnumerable()调用.

您还可以调用CopyToDataTable(),它将在任意IEnumerable上工作[ sic ].但是,它会对行进行深层复制,因此如果您希望用户更新数据,或者您希望用户查看(在代码中)对原始数据行所做的更改,则无效.

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