ASP.NET C#中为单个GridView配置两个数据源的问题
解决单个GridView绑定两个数据源的问题
问题根源
你的代码无法正常显示数据的原因有两个:
- GridView未绑定任何数据源:没有给GridView指定
DataSource并执行DataBind(),导致不会生成数据行,RowDataBound事件也不会触发(仅表头会渲染)。 - DataItem无法跨数据源获取字段:即使绑定了某一个数据源,该行的
DataItem仅包含当前数据源的字段,无法直接获取另一个数据源的Name或Country值。
以下提供两种无需SQL端操作(存储过程/联表)的解决方案,完全在Visual Studio的ASP.NET代码中实现:
方案一:合并两个数据源为统一DataTable后绑定
这种方式将两个数据源的数据合并到一个新的DataTable中,再绑定到GridView,逻辑清晰且易于维护。
前端代码(保持原结构即可)
<asp:GridView ID="GridView1" runat="server"> <Columns> <asp:BoundField DataField="BasSaat" HeaderText="BasSaat" /> <asp:BoundField DataField="Ad" HeaderText="Ad" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:RemoteConnect %>" SelectCommand="SELECT [Name] FROM [Table1]"></asp:SqlDataSource> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:RemoteConnect %>" SelectCommand="SELECT [Country] FROM [Table2]"></asp:SqlDataSource>
后台代码
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 从两个SqlDataSource中提取数据 DataTable dtCountry = GetDataSourceData(SqlDataSource1); DataTable dtName = GetDataSourceData(SqlDataSource2); // 创建合并后的DataTable,对应GridView的列 DataTable mergedTable = new DataTable(); mergedTable.Columns.Add("BasSaat", typeof(string)); mergedTable.Columns.Add("Ad", typeof(string)); // 处理两个数据源行数不一致的情况,取最大行数填充 int maxRowCount = Math.Max(dtCountry.Rows.Count, dtName.Rows.Count); for (int i = 0; i < maxRowCount; i++) { DataRow newRow = mergedTable.NewRow(); // 填充第一个列(来自SqlDataSource1的Country) newRow["BasSaat"] = i < dtCountry.Rows.Count ? dtCountry.Rows[i]["Country"].ToString() : string.Empty; // 填充第二个列(来自SqlDataSource2的Name) newRow["Ad"] = i < dtName.Rows.Count ? dtName.Rows[i]["Name"].ToString() : string.Empty; mergedTable.Rows.Add(newRow); } // 绑定合并后的表到GridView GridView1.DataSource = mergedTable; GridView1.DataBind(); } } // 辅助方法:从SqlDataSource获取DataTable private DataTable GetDataSourceData(SqlDataSource dataSource) { DataView dataView = (DataView)dataSource.Select(DataSourceSelectArguments.Empty); return dataView.ToTable(); }
方案二:绑定单个数据源,在RowDataBound中填充第二个数据源数据
这种方式先绑定其中一个数据源,再在行绑定事件中从另一个数据源提取对应行的数据填充到列中。
前端代码(保持原结构,保留RowDataBound事件)
<asp:GridView ID="GridView1" runat="server" OnRowDataBound="GridView1_RowDataBound"> <Columns> <asp:BoundField DataField="BasSaat" HeaderText="BasSaat" /> <asp:BoundField DataField="Ad" HeaderText="Ad" /> </Columns> </asp:GridView> <asp:SqlDataSource ID="SqlDataSource2" runat="server" ConnectionString="<%$ ConnectionStrings:RemoteConnect %>" SelectCommand="SELECT [Name] FROM [Table1]"></asp:SqlDataSource> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:RemoteConnect %>" SelectCommand="SELECT [Country] FROM [Table2]"></asp:SqlDataSource>
后台代码
// 存储第二个数据源的数据,供RowDataBound事件使用 private List<string> _nameList; protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { // 提取SqlDataSource2的Name数据并存储 DataTable dtName = GetDataSourceData(SqlDataSource2); _nameList = dtName.AsEnumerable().Select(row => row["Name"].ToString()).ToList(); // 绑定SqlDataSource1到GridView GridView1.DataSource = SqlDataSource1; GridView1.DataBind(); } } private DataTable GetDataSourceData(SqlDataSource dataSource) { DataView dataView = (DataView)dataSource.Select(DataSourceSelectArguments.Empty); return dataView.ToTable(); } protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == DataControlRowType.DataRow) { // 填充第一个列:当前绑定数据源的Country字段 e.Row.Cells[0].Text = ((DataRowView)e.Row.DataItem)["Country"].ToString(); // 填充第二个列:从预存的列表中取对应索引的数据,超出范围则为空 int rowIndex = e.Row.RowIndex; e.Row.Cells[1].Text = rowIndex < _nameList.Count ? _nameList[rowIndex] : string.Empty; } }
内容的提问来源于stack exchange,提问作者Ali Mohammad alizadeh
相关产品推荐
相关产品推荐

