You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

绑定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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 03:15:40