关于VB.NET中实现嵌套数据控件中数据绑定的问题
LanFan [原创]
在ASP.NET中经常会用到嵌套的数据控件,比如Repeater、DataList、DataGrid等的相互嵌套。在嵌套的数据控件中通常采用父表和子表的形式绑定数据,将父表数据绑定到最外层数据控件,子表数据绑定到内层数据控件。对于该数据绑定问题网上已有很多讨论,但用C#实现的居多,在VB.NET中很多人遇到了一些问题。
我使用比较简单的Repeater嵌套Repeater做为例子,在此我借用kwklover在《ASP.NET的层次数据显示技术》中的例子。在数据绑定中关键的一句语句在C#中是如下形式:
<asp:repeater id="ChildRepeater" datasource='<%# ((DataRow)Container.DataItem).GetChildRows("RelationName") %>' runat="server">
<itemtemplate>
职员:<%# DataBinder.Eval(Container.DataItem, "[/"lname/"]")%>=
<%# DataBinder.Eval(Container.DataItem, "[/"fname/"]")%><br>
</itemtemplate>
</asp:repeater>
我们把该句转换到VB中则为:
<asp:repeater id="ChildRepeater" datasource='<%# CType(Container.DataItem,DataRowView).Row.GetChildRows("RelationName") %>' runat="server">
<itemtemplate>
职员: <%# DataBinder.Eval(Container.DataItem, "lname")%> =
<%# DataBinder.Eval(Container.DataItem, "fname")%> <br>
</itemtemplate>
</asp:repeater>
编译时将会出现 "DataBinder.Eval:“System.Data.DataRow”不包含名称为 lname 的属性" 的错误
经过多次试验,得到了解决这个问题的两种方法:
一、就是kwklover在《ASP.NET的层次数据显示技术》中采用的,使用CreateChildView方法:
完整的例子是这样
import System.Data
import System.Data.SqlClient
dim objConn as new SqlConnection("Data Source=Localhost;Database=Pubs;userid=sa;password=sa")
objConn.Open()
dim strSql as string="Select * from jobs;Select * from employee"
dim objAdapter as new SqlDataAdapter(strSql,objConn)
dim objDs as new DataSet()
objAdapter.Fill(objDs)
objConn.Close()
'设定两个表的名称
objDs.Tables(1).TalbeName="jobs"
objDs.Tables(0).TableName="employee"
'为这两个表添加关系
dim Parent as DataColumn=objDs.Tables("jobs").Columns("job_id")
dim Child as DataColumn=objDs.Tables("employee").Columns("job_id")
objDs.Relations.Add("RelationName",Parent,Child)
'数据绑定到ParentRepeater:
ParentRepeater.DataSource=objDs.Tables("jobs").DefaultView
ParentRepeater.DataBind()
在html里加入下面的代码:
<asp:repeater id="ParentRepeater" runat="server">
<itemtemplate>
职位:<%# DataBinder.Eval(Container.DataItem,"job_desc") %><br>
<asp:repeater id="ChildRepeater" runat="server" DataSource='<%# CType(Container.DataItem,DataRowView).CreateChildView("RelationName") %>'>
<itemtemplate>
职员:<%# DataBinder.Eval(Container.DataItem,"lname") %>
<%# DataBinder.Eval(Container.DataItem,"fname") %>
</itemtemplate>
</asp:repeater>
</itemtemplate>
</asp:repeater>
二、将<%# DataBinder.Eval(Container.DataItem, "lname")%>改为
<%# DataBinder.Eval(Container.DataItem, "(lname)")%>
即:
<asp:repeater id="ChildRepeater" datasource='<%# CType(Container.DataItem,DataRowView).Row.GetChildRows("RelationName") %>' runat="server">
<itemtemplate>
职员: <%# DataBinder.Eval(Container.DataItem, "(lname)")%> =
<%# DataBinder.Eval(Container.DataItem, "(fname)")%> <br>
</itemtemplate>
</asp:repeater>
我个人认为因为GetChildRows返回的是DataRow集合不是DataTable,子表中Container.DataItem中的内容是DataRow,DataBinder.Eval把"lname"作为DataRow的属性连接成DataRow.lname,因此出现"DataBinder.Eval:“System.Data.DataRow”不包含名称为 lname 的属性"的错误,而当我们"lname"改为"(lname)"后DataBinder.Eval则把二者连接为DataRow("lname")因此能正确编译,改为"[lname]"也可以。
另外,还可以直接写成: <%# Container.DataItem("lname") %>