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

发布时间:2026/10/30 14:29:22

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 的组合不新但在维护型项目里它是最省心的那条路。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/30 14:24:21

清明祭祀墓园后端源码2.0.8:架构设计与高并发实战解析

简介:这是一份清明祈福祭祀墓园系统的后端源码包,定位于服务祭扫类网站的逻辑层,面向需要实现祈福记录、祭祀预约、留言管理等功能的开发者。压缩包共135个文件,主要由54个HTML页面模板、29个PHP业务脚本、16个JavaScript交互脚本…

2026/10/30 14:24:21

Spring Boot服装销售平台:库存锁+订单幂等+真实联调

简介:这是一套基于Spring Boot与Vue技术栈开发的服装销售平台完整源码,面向Java Web初学者、毕业设计学生及中小型电商系统学习者,解决从需求分析到前后端联调的全流程实践问题。资源包共862个文件,涵盖146个Java后端逻辑文件、15…

2026/10/30 14:24:21

C# OpenCvSharp人脸识别实战:从LBPH到ArcFace的完整工程落地

简介:本资源是一套基于C#与OpenCV(通过Emgu CV封装)实现的人脸识别完整工程实践项目,面向.NET开发者、计算机视觉初学者及高校课程设计者,解决Windows平台下人脸检测、特征提取与身份识别的落地问题。压缩包共94个文件…

2026/10/30 15:24:33

OpenPortalServer:轻量级PORTAL协议服务端实战指南

简介:OpenPortalServer V3.3.5.6 是一款基于 Java 开发的开源 Portal 协议服务端程序,专为网络认证网关场景设计,适用于需对接华为、H3C、锐捷、爱快、iKuai 等主流厂商设备的系统集成工程师、校园/企业 Portal 认证平台开发者及网络安全运维…

2026/10/30 15:19:32

微信小程序与SSM后端联调指南:从接口配置到避坑实践

简介:这是一套微信小程序与SSM后端整合开发的完整案例资源,定位为家庭大厨场景的食谱分享与家常菜教学应用。项目采用前后端分离架构:小程序负责界面展示与用户交互,Spring、SpringMVC、MyBatis组成的后端服务负责业务逻辑与数据持…

2026/10/30 15:14:31

Java医院HIS系统源码:Spring Boot全链路医疗业务实现

简介:这是一套基于SpringBoot开发的Java医院信息系统(HIS)完整源码,面向Java后端开发者、医疗信息化初学者及毕业设计需求者,解决医院门诊挂号、住院管理、药房仓库等核心业务系统从零搭建与二次开发的学习痛点。资源包…

2026/10/29 17:05:52

全国计算机二级C语言真题PDF高效刷题指南

简介:这份PDF是全国计算机二级C语言考试的试题与答案解析,专为备考二级C语言的考生准备。内容涵盖C语言特点与设计理念、程序基本组成单位、main函数执行流程、函数嵌套调用规则、标识符命名规范、整型实型字符型数据类型、八进制十六进制数合法形式、运…

2026/10/29 17:06:02

requests+BeautifulSoup:爬虫抓取h1标题的入门实战指南

简介:一份以实战为导向的Python爬虫入门资源,面向具备基本编程基础、希望快速掌握网络数据抓取的初学者,可解决从零编写简单爬虫的常见困惑。实例以requests库发送HTTP请求、BeautifulSoup解析HTML文档,完整演示从网页中提取 标题…

2026/10/29 17:06:13

递推最小二乘参数辨识MATLAB编程:二阶系统与渐消记忆实现

简介:这是一篇面向控制系统、信号处理与机器学习等领域学习者的最小二乘参数辨识程序说明文档。资源共包含一个docx格式文档,压缩包大小七十八KB,内容围绕递推最小二乘算法和渐消记忆最小二乘算法展开:先构造一个极点位于单位圆内…

2026/10/30 0:00:46

NCP1342高频准谐振反激控制器:从设计约束到验收的完整方案

简介:NCP1342 高频准谐振反激控制器应用介绍译文文档,面向电源设计工程师、硬件研发人员及开关电源学习者,帮助读者跨越英文原版资料的语言门槛,系统理解这款高集成度 QR Flyback 控制器的设计要点。文档围绕芯片核心特性展开&…

2026/10/30 0:00:46

NCP1342准谐振反激电源设计:从选型到验收的全流程解析

简介:这份文档面向电源设计工程师与开关电源学习者,系统梳理NCP1342高频准谐振反激控制器的应用要点,帮助读者快速理解这款高集成度离线电源变换器控制芯片的工作机制与设计方法。内容涵盖芯片核心特性、引脚功能定义、电气特性参数表、最大额…

2026/10/30 0:00:46

Web系统自动登出机制设计与实现全解析

1. 系统自动登出机制的设计初衷在各类Web应用和后台管理系统中,自动登出功能早已成为标配。这个看似简单的功能背后,实际上涉及用户安全、资源管理和体验优化的多重考量。作为从业十多年的老开发,我见过太多因为登出逻辑设计不当导致的安全事…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑