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

VB 4.8网页开发:GridView索引重组后DetailsView编辑功能异常

问题:手动绑定DataTable时DetailsView编辑命令失效

业务场景为销售页面,需重组GridView的ID索引,采用动态构建DataTable的方式填充DetailsView。当前遇到两个核心问题:

  • 手动为DetailsView分配DataSource并执行DataBind()后,编辑命令完全失效,无法切换到显示「更新/取消」控件的编辑模式
  • 若直接通过DataSourceID绑定数据源,编辑功能可正常工作,但会破坏数据库索引的有序性,不符合业务需求

原始代码

Sub SortOrder_Item(ByVal Sender As Object, ByVal e As GridViewCommandEventArgs) Handles SortOrder.RowCommand
    Dim workTable As New System.Data.DataTable
            
    Dim DTabRow As System.Data.DataRow = workTable.NewRow

    Dim index As Integer = Convert.ToInt32(e.CommandArgument)           

    Dim Din As GridViewRow = SortOrder.Rows(index)
    if e.CommandName = "Add" Then
    Dim workCol As System.Data.DataColumn = workTable.Columns.Add("ID", Type.GetType("System.Int32"))
        workCol.AllowDBNull = false
        workCol.Unique = false
        Dim _Item_Name As String = Server.HTMLDecode(Din.Cells(1).Text)
        Dim _Curr_Price As Int32 = Server.HTMLDecode(Din.Cells(4).Text)
        Dim _REFNo As String = Server.HTMLDecode(Din.Cells(5).Text)
        Dim Dout As Int32 = index +1

        workCol = New System.Data.DataColumn()
        workCol.DataType = System.Type.GetType("System.String") 
        workCol.AllowDBNull = True
        workCol.Caption = ""
        workCol.ColumnName = "ItemName" & Dout 
        workCol.DefaultValue = ""
        workTable.Columns.Add(workCol)

        workCol = New System.Data.DataColumn()
        workCol.DataType = System.Type.GetType("System.Double") 
        workCol.AllowDBNull = True 
        workCol.Caption = ""
        workCol.ColumnName = "Curr_Price" & Dout
        workCol.DefaultValue = 0
        workTable.Columns.Add(workCol)
                        
        workCol = New System.Data.DataColumn()
            workCol.DataType = System.Type.GetType("System.String") 
            workCol.AllowDBNull = True 
            workCol.Caption = ""
            workCol.ColumnName = "REFNo" & Dout
            workCol.DefaultValue = ""
            workTable.Columns.Add(workCol)
        
        workCol = New System.Data.DataColumn()
            DTabRow("ID") = Dout
            DTabRow("ItemName" & Dout) = _Item_Name
            DTabRow("Curr_Price" & Dout) = _Curr_Price
            DTabRow("REFNo" & Dout) = _REFNo
        
            workTable.Rows.Add(DTabRow)
            DetailInsert.DataSource = workTable
            DetailInsert.DataBind()
            SortOrder.Enabled = False
        Go_NET.Visible = True
        else
            Go_NET.Visible = False
        end if
End Sub

            
  Sub CustomerDetailsView_ItemUpdating(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs)


  End Sub

  Sub CustomerDetailsView_ModeChanging(ByVal sender As Object, ByVal e As DetailsViewModeEventArgs)
  
    If e.CancelingEdit Then
      
      ' The user canceled the update operation.
      ' Clear the error message label.
      MesX1.Text = ""
    End If
    
  End Sub

问题根源

  1. 动态列名导致字段映射失效:代码中给列名拼接了Dout后缀(如ItemName1、Curr_Price2),但DetailsView的字段绑定是固定的,动态列名无法匹配控件模板中的DataField属性,导致编辑模式无法触发。
  2. 未设置DataTable主键:DetailsView进入编辑模式需要明确的主键来定位目标行,代码中虽添加了ID列,但未将其设为DataTable的主键,控件无法识别唯一行标识。
  3. 未持久化数据源:每次页面回发时,手动构建的DataTable会被销毁,导致DetailsView丢失数据源,编辑状态无法维持。

修复方案

1. 重构DataTable结构,使用固定列名并设置主键

Sub SortOrder_Item(ByVal Sender As Object, ByVal e As GridViewCommandEventArgs) Handles SortOrder.RowCommand
    If e.CommandName = "Add" Then
        Dim workTable As New System.Data.DataTable
        
        ' 添加主键ID列
        Dim idCol As System.Data.DataColumn = workTable.Columns.Add("ID", GetType(Integer))
        idCol.AllowDBNull = False
        idCol.Unique = True
        workTable.PrimaryKey = New System.Data.DataColumn() {idCol} ' 设置主键
        
        ' 添加固定名称的业务列
        workTable.Columns.Add("ItemName", GetType(String)).DefaultValue = ""
        workTable.Columns.Add("Curr_Price", GetType(Double)).DefaultValue = 0
        workTable.Columns.Add("REFNo", GetType(String)).DefaultValue = ""

        Dim index As Integer = Convert.ToInt32(e.CommandArgument)           
        Dim Din As GridViewRow = SortOrder.Rows(index)
        Dim _Item_Name As String = Server.HtmlDecode(Din.Cells(1).Text)
        ' 修正类型转换错误:价格应为Double而非Int32
        Dim _Curr_Price As Double = Convert.ToDouble(Server.HtmlDecode(Din.Cells(4).Text))
        Dim _REFNo As String = Server.HtmlDecode(Din.Cells(5).Text)
        Dim Dout As Int32 = index +1

        ' 填充行数据
        Dim DTabRow As System.Data.DataRow = workTable.NewRow()
        DTabRow("ID") = Dout
        DTabRow("ItemName") = _Item_Name
        DTabRow("Curr_Price") = _Curr_Price
        DTabRow("REFNo") = _REFNo
        workTable.Rows.Add(DTabRow)

        ' 保存DataTable到ViewState,持久化数据源
        ViewState("WorkTable") = workTable
        DetailInsert.DataSource = workTable
        DetailInsert.DataBind()
        SortOrder.Enabled = False
        Go_NET.Visible = True
    Else
        Go_NET.Visible = False
    End If
End Sub

2. 修正DetailsView的ASPX配置,确保字段绑定匹配

<asp:DetailsView ID="DetailInsert" runat="server" 
    AutoGenerateEditButton="True"
    DataKeyNames="ID" ' 指定主键字段
    OnItemUpdating="CustomerDetailsView_ItemUpdating" 
    OnModeChanging="CustomerDetailsView_ModeChanging">
    <Fields>
        <asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True" />
        <asp:BoundField DataField="ItemName" HeaderText="商品名称" />
        <asp:BoundField DataField="Curr_Price" HeaderText="当前价格" />
        <asp:BoundField DataField="REFNo" HeaderText="参考编号" />
    </Fields>
</asp:DetailsView>

3. 完善ItemUpdating事件逻辑,实现编辑更新

Sub CustomerDetailsView_ItemUpdating(ByVal sender As Object, ByVal e As DetailsViewUpdateEventArgs)
    Dim dv As DetailsView = DirectCast(sender, DetailsView)
    ' 从ViewState中获取持久化的DataTable
    Dim workTable As DataTable = DirectCast(ViewState("WorkTable"), DataTable)
    
    ' 通过主键ID定位要更新的行
    Dim rowId As Integer = Convert.ToInt32(dv.DataKey.Value)
    Dim targetRow As DataRow = workTable.Rows.Find(rowId)
    
    ' 更新字段值
    targetRow("ItemName") = e.NewValues("ItemName").ToString()
    targetRow("Curr_Price") = Convert.ToDouble(e.NewValues("Curr_Price"))
    targetRow("REFNo") = e.NewValues("REFNo").ToString()
    
    ' 切换回只读模式并重新绑定数据
    dv.ChangeMode(DetailsViewMode.ReadOnly)
    dv.DataSource = workTable
    dv.DataBind()
    
    ' 恢复GridView可用状态
    SortOrder.Enabled = True
End Sub

4. 优化ModeChanging事件,维持页面状态

Sub CustomerDetailsView_ModeChanging(ByVal sender As Object, ByVal e As DetailsViewModeEventArgs)
    Dim dv As DetailsView = DirectCast(sender, DetailsView)
    dv.ChangeMode(e.NewMode)
    
    ' 重新绑定ViewState中的数据源,确保模式切换后控件显示正常
    dv.DataSource = DirectCast(ViewState("WorkTable"), DataTable)
    dv.DataBind()
    
    If e.CancelingEdit Then
        MesX1.Text = ""
    End If
End Sub

内容的提问来源于stack exchange,提问作者Ian Burton

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 15:31:11