绑定DetailsView到GridView选中行时出现格式错误问题
问题:Web Forms中Suppliers表GridView+DetailsView绑定报错
我正在重新学习Web Forms,用Northwind数据库做后台,采用「顶部GridView展示列表,选中行后在DetailsView显示详情」的模式,这个模式在Customers、Products等表上都正常,但处理Suppliers表时出问题——GridView能正常显示,加了DetailsView后就报错。
GridView及数据源代码
<asp:GridView ID="gvSuppliers" class="table table-bordered table-condensed table-responsive table-hover" runat="server" AutoGenerateColumns="False" autogenerateselectbutton="True" AllowPaging="True" DataSourceID="dsSuppliersObjectSource" DataKeyNames="SupplierID" > <columns> <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" /> <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" /> <asp:BoundField DataField="ContactName" HeaderText="ContactName" SortExpression="ContactName" /> <asp:BoundField DataField="ContactTitle" HeaderText="ContactTitle" SortExpression="ContactTitle" /> <asp:BoundField DataField="Address" HeaderText="Address" SortExpression="Address" /> <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" /> <asp:BoundField DataField="Region" HeaderText="Region" SortExpression="Region" /> <asp:BoundField DataField="PostalCode" HeaderText="PostalCode" SortExpression="PostalCode" /> <asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" /> <asp:BoundField DataField="Phone" HeaderText="Phone" SortExpression="Phone" /> <asp:BoundField DataField="Fax" HeaderText="Fax" SortExpression="Fax" /> <asp:BoundField DataField="HomePage" HeaderText="HomePage" SortExpression="HomePage" /> </columns> </asp:GridView> <asp:ObjectDataSource ID="dsSuppliersObjectSource" runat="server" EnablePaging="True" SelectMethod="GetSuppliers" SelectCountMethod="GetSuppliersCount" TypeName="Unknown_Web_Forms.SupplierDS" MaximumRowsParameterName="maxRows" StartRowIndexParameterName="startIndex"> </asp:ObjectDataSource>
ObjectDataSource后台查询方法
public List<Supplier> GetSuppliers(int startIndex, int maxRows) { using (NorthwindEntities entities = new NorthwindEntities()) { return (from supplier in entities.Suppliers select supplier) .OrderBy(supplier => supplier.SupplierID) .Skip(startIndex) .Take(maxRows).ToList(); } }
报错的DetailsView及数据源代码
<asp:DetailsView ID="DetailsView1" runat="server" Height="50px" Width="125px" AutoGenerateRows="False" DataSourceID="SuppliersSingleItemDataSource"> <Fields> <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" /> <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" SortExpression="CompanyName" /> </Fields> </asp:DetailsView> <asp:SqlDataSource ID="SuppliersSingleItemDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString2 %>" SelectCommand="SELECT * FROM [Suppliers] WHERE ([SupplierID] = @SupplierID)"> <SelectParameters> <asp:ControlParameter ControlID="gvSuppliers" DefaultValue="null" Name="SupplierID" PropertyName="SelectedValue" Type="Int32" /> </SelectParameters> </asp:SqlDataSource>
已尝试的解决方法
- 精简DetailsView的BoundField列,仅保留主键SupplierID和CompanyName字段,排查数据问题
- 确认GridView的DataKeyName(SupplierID)为整数类型,与DetailsView数据源的类型匹配
解决思路
1. 修复参数默认值的类型冲突
SqlDataSource中ControlParameter的DefaultValue="null"是字符串类型,但参数类型设为Int32,页面首次加载无选中行时,会尝试把"null"转int导致报错。修改方案:
- 把
DefaultValue改为"0",或者直接移除该属性 - 给SqlDataSource添加
CancelSelectOnNullParameter="False",这样参数为空时不会执行查询,避免报错
修改后的SqlDataSource:
<asp:SqlDataSource ID="SuppliersSingleItemDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString2 %>" SelectCommand="SELECT * FROM [Suppliers] WHERE ([SupplierID] = @SupplierID)" CancelSelectOnNullParameter="False"> <SelectParameters> <asp:ControlParameter ControlID="gvSuppliers" Name="SupplierID" PropertyName="SelectedValue" Type="Int32" /> </SelectParameters> </asp:SqlDataSource>
2. 统一数据源类型,避免混合使用ObjectDataSource和SqlDataSource
GridView用的是LINQ to Entities的ObjectDataSource,DetailsView却用SqlDataSource,可能存在上下文不一致的隐性问题。可以把DetailsView也改为ObjectDataSource:
- 先在
SupplierDS类中新增获取单条供应商数据的方法:
public Supplier GetSupplierById(int supplierId) { using (NorthwindEntities entities = new NorthwindEntities()) { return entities.Suppliers.FirstOrDefault(s => s.SupplierID == supplierId); } }
- 配置对应的ObjectDataSource:
<asp:ObjectDataSource ID="dsSupplierSingle" runat="server" SelectMethod="GetSupplierById" TypeName="Unknown_Web_Forms.SupplierDS"> <SelectParameters> <asp:ControlParameter ControlID="gvSuppliers" Name="supplierId" PropertyName="SelectedValue" Type="Int32" /> </SelectParameters> </asp:ObjectDataSource>
- 修改DetailsView的
DataSourceID为dsSupplierSingle即可
3. 验证SelectedValue的传递正确性
在GridView的SelectedIndexChanged事件中添加调试代码,确认是否正确获取到SupplierID:
protected void gvSuppliers_SelectedIndexChanged(object sender, EventArgs e) { System.Diagnostics.Debug.WriteLine("选中的SupplierID:" + gvSuppliers.SelectedValue?.ToString()); }
如果输出为空或非预期整数,需要检查:
- GridView的
DataKeyNames是否确实设置为SupplierID - Entity Framework中Supplier实体的SupplierID属性是否正确映射为int类型
4. 确认数据库连接与表结构一致性
- 检查SqlDataSource的
NorthwindConnectionString2是否和ObjectDataSource使用的NorthwindEntities连接的是同一个数据库 - 确认Northwind数据库中Suppliers表的SupplierID字段是int类型,且不允许为空
内容的提问来源于stack exchange,提问作者markaaronky
相关产品推荐
相关产品推荐

