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
问题根源
- 动态列名导致字段映射失效:代码中给列名拼接了
Dout后缀(如ItemName1、Curr_Price2),但DetailsView的字段绑定是固定的,动态列名无法匹配控件模板中的DataField属性,导致编辑模式无法触发。 - 未设置DataTable主键:DetailsView进入编辑模式需要明确的主键来定位目标行,代码中虽添加了ID列,但未将其设为DataTable的主键,控件无法识别唯一行标识。
- 未持久化数据源:每次页面回发时,手动构建的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
相关产品推荐
相关产品推荐

