使用smoothstate.js页面过渡时ASP.NET按钮OnClick事件无法触发求助
嗨,我之前在把smoothstate.js和ASP.NET WebForms结合的时候遇到过一模一样的问题,我来给你拆解下问题根源和解决办法!
问题根源
smoothstate.js是通过AJAX异步加载并替换页面部分DOM(也就是你母版页里的#main容器),但ASP.NET WebForms的服务器控件(比如你的test按钮)依赖完整的页面生命周期:服务器需要在页面初始化时注册这些控件,同时ViewState、事件验证等机制也依赖原始的页面上下文。
当你用smoothstate从Default.aspx跳转到Second.aspx时,新加载的按钮控件并没有被ASP.NET的服务器端上下文识别,点击时的回发请求会因为找不到对应的事件绑定,最终跳回之前的页面,而不是触发ButtonClick1方法。
解决方案
下面是几个经过验证的解决思路,你可以根据自己的场景选择:
1. 在smoothstate加载完成后重新初始化ASP.NET脚本
smoothstate提供了onAfter回调,你可以在页面内容替换完成后,重新初始化ASP.NET的WebForms相关脚本,让新控件被纳入页面生命周期:
$('#main').smoothState({ onAfter: function() { // 重新初始化ASP.NET的Application和PageRequestManager if (typeof Sys !== 'undefined') { Sys.Application.initialize(); if (Sys.WebForms && Sys.WebForms.PageRequestManager) { var prm = Sys.WebForms.PageRequestManager.getInstance(); prm._initialize('<%= Page.ClientID %>', document.forms[0]); } } } });
2. 让smoothstate跳过ASP.NET的表单回发请求
smoothstate默认会拦截所有表单提交,你可以配置它不处理ASP.NET的服务器表单提交,让浏览器用原生方式处理回发:
$('#main').smoothState({ // 关闭对表单的AJAX拦截,让服务器表单正常提交 forms: false, // 或者黑名单排除ASP.NET的提交按钮 blacklist: '[runat="server"][type="submit"]' });
这个方法最直接,因为ASP.NET的回发本来就需要完整的页面上下文,跳过smoothstate的AJAX处理反而更符合WebForms的机制。
3. 手动触发UpdatePanel刷新
如果你依赖UpdatePanel的局部刷新,可以在smoothstate加载完成后,手动触发UpdatePanel的回发,让服务器端识别新的控件:
$('#main').smoothState({ onAfter: function() { // 找到页面中的UpdatePanel并触发回发 var updatePanelId = $('[id*="UpdatePanel"]').attr('id'); if (updatePanelId) { __doPostBack(updatePanelId, ''); } } });
这样UpdatePanel会重新从服务器获取内容,确保控件事件绑定正确。
总结
核心思路就是要么让smoothstate不干扰ASP.NET的回发机制,要么在AJAX加载后重新初始化WebForms的上下文,让服务器控件能被正确识别。我自己当时用的是第二种方法(关闭表单的AJAX拦截),效果很稳定。
内容的提问来源于stack exchange,提问作者CSeem

