ASP.NET WebForms GridView 局部刷新实战:UpdatePanel 与 AJAX 行内编辑

发布时间:2026/10/30 14:30:52
ASP.NET WebForms GridView 局部刷新实战:UpdatePanel 与 AJAX 行内编辑 简介这份资源面向使用 ASP.NET 4.0 与 SQL Server 2008 开发信息系统的开发者针对 VS 自带 GridView 在交互体验与可移植性上的不足提供一套经国外论坛筛选后整理出的实用 GridView 实例。它完整实现了数据的增、删、改操作并以 Ajax 无刷新方式提交适合需要快速搭建后台列表管理页面的初中级 .NET 开发者参考移植。压缩包共 2 个文件以 htm 说明页与 rar 源码包为主整体约 1.52MB体积轻量、结构简单便于直接解压查看与二次改造。目前已有 651 人学习下载说明其在同类控件方案中具备一定参考价值。读者可从中获得可运行的增删改示例代码、Ajax 无刷新交互的实现思路以及可迁移到自身项目的页面组织方式适合作为信息系统开发中的控件选型与功能补全参考。1. 一个老控件的新用法为什么 GridView 配 AJAX 还值得翻出来后台管理页做多了会发现一个规律真正耗时间的不是写业务逻辑而是每次点“编辑”整页刷新、滚动条跳回顶部、筛选条件全丢。某公司内部一套设备台账系统最初就是纯服务端 GridView一页 20 条数据改一个字段要等两秒白屏操作员一天改上百条怨气全撒在开发身上。后来把行内编辑改成 AJAX 局部回发同样的服务器、同样的 SQL Server体感直接从“拨号上网”变成“本地软件”。这份资源就是围绕这个场景整理的ASP.NET WebForms 下的 GridView配合 UpdatePanel 与客户端脚本实现增删改不整页刷新后端仍然走 SqlServer 参数化查询。它不追新框架适合还在维护 WebForms 老系统、又不想推倒重来的团队也适合刚接触 ASP.NET、想弄明白“局部回发到底怎么落地”的新手。下面按“能干什么 → 怎么搭 → 参数怎么调 → 坑在哪”的顺序拆开讲代码可以直接抄。2. 把 GridView 接上 AJAXUpdatePanel 与后端数据层的搭法2.1 先想清楚局部回发的边界UpdatePanel 的本质不是“无刷新”而是“只刷新面板内的内容”。页面整体仍然经历一次完整的回发生命周期只是浏览器端把面板外的 DOM 保留下来。理解这一点后面很多玄学现象就解释得通了面板外的控件值不会自动带回、面板内的 GridView 每次都会重新绑定、ViewState 照样在传。选型上如果只是行内编辑、删除确认、分页这类操作UpdatePanel 足够改动量最小老页面几乎不用重写。如果要做无刷新的复杂联动比如级联下拉、实时搜索更合适的是 PageMethod 或 Web API 加前端请求但那是另一条路。这份资源走的是前者理由是维护成本低团队里谁都能接手。一个容易忽略的点UpdatePanel 必须设置UpdateModeConditional否则面板内任何控件触发回发都会刷新整个面板包括你不想动的分页区。默认是 Always很多人栽在这。2.2 页面骨架ScriptManager 与 UpdatePanel 的放置ScriptManager 必须出现在页面最外层且全页只能有一个。如果用了母版页把它放在母版里内容页不要再放第二个否则运行时报“只能有一个 ScriptManager”的错。%-- 母版页或页面顶部全局脚本管理器 --% asp:ScriptManager IDsmMain runatserver EnablePartialRenderingtrue / %-- 只包裹需要局部刷新的区域不要把整页塞进去 --% asp:UpdatePanel IDupGrid runatserver UpdateModeConditional ChildrenAsTriggerstrue ContentTemplate asp:GridView IDgvDevice runatserver AutoGenerateColumnsfalse DataKeyNamesDeviceId OnRowEditinggvDevice_RowEditing OnRowUpdatinggvDevice_RowUpdating OnRowCancelingEditgvDevice_RowCancelingEdit OnRowDeletinggvDevice_RowDeleting OnPageIndexChanginggvDevice_PageIndexChanging AllowPagingtrue PageSize20 Columns asp:BoundField DataFieldDeviceName HeaderText设备名 / asp:TemplateField HeaderText状态 ItemTemplate%# Eval(Status) %/ItemTemplate EditItemTemplate asp:DropDownList IDddlStatus runatserver SelectedValue%# Bind(Status) % asp:ListItem Text在用 Value1 / asp:ListItem Text停用 Value0 / /asp:DropDownList /EditItemTemplate /asp:TemplateField asp:CommandField ShowEditButtontrue ShowDeleteButtontrue / /Columns /asp:GridView /ContentTemplate Triggers %-- 显式声明异步触发器避免整页回发 --% asp:AsyncPostBackTrigger ControlIDgvDevice EventNameRowUpdating / /Triggers /asp:UpdatePanel逻辑说明DataKeyNames是行内编辑的命门没有它RowUpdating里拿不到主键更新会静默失败。UpdateModeConditional配合ChildrenAsTriggerstrue表示面板内控件触发时刷新面板外部触发不刷新。AsyncPostBackTrigger显式声明哪些事件走异步比依赖默认行为更可控。参数上PageSize建议 1525 之间太大单次回发数据量上去局部刷新也救不了体感太小分页点击频繁反而增加回发次数。EnablePartialRendering保持 true这是局部渲染的总开关。2.3 后端数据层参数化查询与分页数据访问不要拼字符串这是血泪经验。下面用SqlCommand参数化写法分页用ROW_NUMBER()兼容 SqlServer 2005 以后的版本。// 数据访问类分页查询 参数化更新 public DataTable GetDevices(int pageIndex, int pageSize) { string sql SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY DeviceId) AS RowNum, * FROM Device ) t WHERE t.RowNum BETWEEN Start AND End; using (var conn new SqlConnection(_connStr)) using (var cmd new SqlCommand(sql, conn)) { // 参数化杜绝注入Start/End 由页码换算 cmd.Parameters.Add(Start, SqlDbType.Int).Value (pageIndex - 1) * pageSize 1; cmd.Parameters.Add(End, SqlDbType.Int).Value pageIndex * pageSize; var dt new DataTable(); new SqlDataAdapter(cmd).Fill(dt); return dt; } } // 行更新主键从 DataKeys 取字段值从编辑行取 protected void gvDevice_RowUpdating(object sender, GridViewUpdateEventArgs e) { int id Convert.ToInt32(gvDevice.DataKeys[e.RowIndex].Value); var row gvDevice.Rows[e.RowIndex]; string name ((TextBox)row.Cells[0].Controls[0]).Text; string status ((DropDownList)row.FindControl(ddlStatus)).SelectedValue; const string sql UPDATE Device SET DeviceNameName, StatusStatus WHERE DeviceIdId; using (var conn new SqlConnection(_connStr)) using (var cmd new SqlCommand(sql, conn)) { cmd.Parameters.Add(Name, SqlDbType.NVarChar, 50).Value name; cmd.Parameters.Add(Status, SqlDbType.Int).Value int.Parse(status); cmd.Parameters.Add(Id, SqlDbType.Int).Value id; conn.Open(); cmd.ExecuteNonQuery(); } gvDevice.EditIndex -1; // 退出编辑态 BindGrid(); // 重新绑定面板内刷新 }逻辑说明ROW_NUMBER()分页避免了TOP加偏移的写法在深分页时的性能塌陷。更新时主键从DataKeys取而不是从界面读防止用户篡改隐藏字段。BindGrid()放在更新之后保证面板内显示的是数据库最新值而不是回发前的旧 ViewState。参数说明Name的NVarChar, 50显式指定长度避免 SqlServer 按实际长度推断导致执行计划缓存膨胀Status用 Int 而不是字符串减少隐式转换。EditIndex -1必须在重新绑定前设置否则 GridView 会试图在已失效的行上恢复编辑态抛“索引超出范围”。2.4 删除与分页的异步处理删除和分页同理关键是每次操作后重置编辑态并重新绑定。分页时NewPageIndex要判断边界防止用户手改查询串导致越界。protected void gvDevice_RowDeleting(object sender, GridViewDeleteEventArgs e) { int id Convert.ToInt32(gvDevice.DataKeys[e.RowIndex].Value); using (var conn new SqlConnection(_connStr)) using (var cmd new SqlCommand(DELETE FROM Device WHERE DeviceIdId, conn)) { cmd.Parameters.Add(Id, SqlDbType.Int).Value id; conn.Open(); cmd.ExecuteNonQuery(); } gvDevice.EditIndex -1; BindGrid(); } protected void gvDevice_PageIndexChanging(object sender, GridViewPageEventArgs e) { // 边界保护页码不能小于 0也不能超过总页数 int newIndex Math.Max(0, e.NewPageIndex); gvDevice.PageIndex newIndex; gvDevice.EditIndex -1; BindGrid(); }逻辑说明删除后同样要退出编辑态否则被删行如果正处于编辑状态重新绑定会报错。分页的Math.Max(0, ...)是后悔药防止负数页码。真实项目里还应校验newIndex不超过PageCount - 1这里省略是为了聚焦主流程。3. 参数与性能让局部刷新真的快起来3.1 ViewState 与数据量的取舍GridView 默认把整张表的数据塞进 ViewState20 条不多200 条就明显了。局部刷新虽然不白屏但每次回发仍要把 ViewState 传回服务器体积大了照样卡。常见做法是关闭 GridView 的 ViewState改为每次回发重新查库asp:GridView IDgvDevice runatserver EnableViewStatefalse ... /代价是每次回发都查一次数据库但配合分页每页 20 条查询成本远低于传输几百 KB 的 ViewState。如果数据量小、查询频繁也可以保留 ViewState 换取少查库这属于典型的时间换空间按实际压测决定。3.2 异步回发的进度提示局部刷新期间用户看不到任何反馈容易重复点击。加一个UpdateProgress超过 300 毫秒才显示避免一闪而过asp:UpdateProgress IDupProg runatserver AssociatedUpdatePanelIDupGrid DisplayAfter300 ProgressTemplate div classloading处理中…/div /ProgressTemplate /asp:UpdateProgressDisplayAfter单位是毫秒设太小会频繁闪烁设太大用户以为没反应300500 是常见区间。AssociatedUpdatePanelID必须和面板 ID 一致否则不生效。3.3 关键参数速查参数位置建议值作用UpdateModeUpdatePanelConditional避免无关回发刷新面板ChildrenAsTriggersUpdatePaneltrue面板内控件触发刷新PageSizeGridView1525平衡单次数据量与分页频率EnableViewStateGridView视数据量关闭可减小回发体积DisplayAfterUpdateProgress300500控制加载提示出现时机DataKeyNamesGridView必填主键行操作取主键的依据4. 避坑排查五个真实翻车现场4.1 点编辑没反应页面整页刷新现象点“编辑”后整页白屏刷新滚动条回顶。原因GridView 不在 UpdatePanel 的 ContentTemplate 内或者 ScriptManager 缺失。解决确认 GridView 被 ContentTemplate 包裹且页面或母版有且仅有一个 ScriptManagerEnablePartialRenderingtrue。4.2 更新成功但界面还是旧值现象数据库已改GridView 显示的还是修改前的内容。原因RowUpdating里忘了重新绑定或者EditIndex没重置就绑定。解决更新后先EditIndex -1再调用BindGrid()顺序不能反。4.3 行内编辑取不到主键现象DataKeys[e.RowIndex].Value抛空引用或返回 0。原因GridView 没设DataKeyNames或者设了但绑定的 DataTable 里没有该列。解决DataKeyNamesDeviceId必须与查询结果列名完全一致大小写敏感的场景要核对。4.4 面板内下拉框选中值丢失现象编辑行里的 DropDownList 每次回发都回到第一项。原因Bind(Status)绑定的字段类型和ListItem的 Value 类型不一致或者 ViewState 被关闭后没有在回发时重新赋值。解决统一用字符串或统一用整型关闭 ViewState 时在RowDataBound里手动设置SelectedValue。4.5 分页后编辑态错乱现象在第 2 页点编辑翻到第 1 页后报“索引超出范围”。原因EditIndex是全局状态翻页后仍指向旧行号。解决PageIndexChanging里先EditIndex -1再改PageIndex最后绑定三步顺序固定。5. 进阶技巧用客户端脚本兜住服务端的边界UpdatePanel 能解决大部分场景但有两个它兜不住的一是删除前的二次确认二是编辑时的前端校验。这两件事放在服务端做体验会打折。我的习惯是在RowDataBound里给删除按钮挂OnClientClick用return confirm(...)拦截确认后才走异步回发。protected void gvDevice_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType DataControlRowType.DataRow) { // 给删除按钮挂客户端确认避免误删 var btnDelete (LinkButton)e.Row.Cells[2].Controls[0]; btnDelete.OnClientClick return confirm(确认删除这条记录删除后不可恢复。);; } }逻辑说明OnClientClick返回 false 时不会触发回发等于在客户端就拦住了。注意Cells索引要和列顺序对应CommandField生成的按钮在对应单元格的Controls[0]列顺序一变索引就得跟着改这是最容易翻车的地方建议用FindControl或给按钮加 ID 更稳。再进一步如果要做“编辑时实时校验设备名是否重复”可以在RowUpdating之前用PageMethods发一个轻量请求查重但这会引入额外的服务端方法暴露安全边界要自己评估。我的做法是查重放在服务端RowUpdating里做前端只做格式校验非空、长度职责分清维护起来不打架。验证方法很简单打开浏览器开发者工具的网络面板点一次编辑看请求是不是只回传了面板相关的数据、响应是不是只更新了局部 HTML。如果看到整页 HTML 返回说明 UpdatePanel 没生效回去查 ScriptManager 和包裹关系。另外用 SqlServer Profiler 抓一次更新确认执行的是参数化语句而不是拼接字符串这一步能提前发现注入隐患。从那以后我每次接 WebForms 老项目都强制先跑一遍“编辑—取消—翻页—删除”四连操作看有没有整页刷新和编辑态残留再谈加功能。这套 GridView 加 AJAX 的组合不新但在维护型项目里它是最省心的那条路。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询