Asp.net 如何避免在AutoPostBack上滚动UpdatePanel?
我在updatepanel中有一个ASP.NET FormView。我通过为FormView中的每个项设置AutoPostBack=true来自动保存表单 这意味着用户可以快速连续单击几个元素,并几乎同时启动几个异步回发 我遇到的问题是,当异步回发尚未完成时,用户能够继续向下滚动表单。浏览器总是滚动回第一次回发时的位置 Page.MaintainScrollPositionOnPostback设置为False 我在ajax和jquery中尝试了各种方法,包括:Asp.net 如何避免在AutoPostBack上滚动UpdatePanel?,asp.net,updatepanel,scroll,autopostback,Asp.net,Updatepanel,Scroll,Autopostback,我在updatepanel中有一个ASP.NET FormView。我通过为FormView中的每个项设置AutoPostBack=true来自动保存表单 这意味着用户可以快速连续单击几个元素,并几乎同时启动几个异步回发 我遇到的问题是,当异步回发尚未完成时,用户能够继续向下滚动表单。浏览器总是滚动回第一次回发时的位置 Page.MaintainScrollPositionOnPostback设置为False 我在ajax和jquery中尝试了各种方法,包括: 页面加载 添加初始化请求 添加请
- 页面加载
- 添加初始化请求
- 添加请求
- 准备好了吗
- 等等李>
更新 多亏了@chprpipr,我才得以实现这一目标。以下是我的简化解决方案:
var FormScrollerProto = function () {
var Me = this;
this.lastScrollPos = 0;
var myLogger;
this.Setup = function (logger) {
myLogger = logger;
// Bind a function to the window
$(window).bind("scroll", function () {
// Record the scroll position
Me.lastScrollPos = Me.GetScrollTop();
myLogger.Log("last: " + Me.lastScrollPos);
});
}
this.ScrollForm = function () {
// Apply the last scroll position
$(window).scrollTop(Me.lastScrollPos);
}
// Call this in pageRequestManager.EndRequest
this.EndRequestHandler = function (args) {
myLogger.Log(args.get_error());
if (args.get_error() == undefined) {
Me.ScrollForm();
}
}
this.GetScrollTop = function () {
return Me.FilterResults(
window.pageYOffset ? window.pageYOffset : 0,
document.documentElement ? document.documentElement.scrollTop : 0,
document.body ? document.body.scrollTop : 0
);
}
this.FilterResults = function (n_win, n_docel, n_body) {
var n_result = n_win ? n_win : 0;
if (n_docel && (!n_result || (n_result > n_docel)))
n_result = n_docel;
return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result;
}
}
主页:
...snip...
var logger;
var FormScroller;
// Hook up Application event handlers.
var app = Sys.Application;
// app.add_load(ApplicationLoad); - use pageLoad instead
app.add_init(ApplicationInit);
// app.add_disposing(ApplicationDisposing);
// app.add_unload(ApplicationUnload);
// Application event handlers for component developers.
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm.get_isInAsyncPostBack()) {
prm.add_initializeRequest(InitializeRequest);
prm.add_beginRequest(BeginRequest);
prm.add_pageLoading(PageLoading);
prm.add_pageLoaded(PageLoaded);
prm.add_endRequest(EndRequest);
}
// Set up components
logger = new LoggerProto();
logger.Init(true);
logger.Log("APP:: Application init.");
FormScroller = new FormScrollerProto();
}
function InitializeRequest(sender, args) {
logger.Log("PRM:: Initializing async request.");
FormScroller.Setup(logger);
}
...snip...
function EndRequest(sender, args) {
logger.Log("PRM:: End of async request.");
maintainScroll(sender, args);
// Display any errors
processErrors(args);
}
...snip...
function maintainScroll(sender, args) {
logger.Log("maintain: " + winScrollTop);
FormScroller.EndRequestHandler(args);
}
我还尝试调用EndRequestHandler(必须删除args.error检查),查看它是否减少了滚动时的闪烁,但没有。值得注意的是,完美的解决方案是完全停止浏览器试图滚动——现在存在一种暂时的抖动,这在拥有大量用户的应用程序中是不可接受的
(滚动顶部代码不是我的-在web上找到。)
(以下是一个关于客户端生命周期的有用MSDN页面:)
3月7日更新: 我刚刚找到了一个非常简单的方法:
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(beginRequest);
function beginRequest()
{
prm._scrollPosition = null;
}
</script>
var prm=Sys.WebForms.PageRequestManager.getInstance();
prm.添加_beginRequest(beginRequest);
函数beginRequest()
{
prm.\u scrollPosition=null;
}
您可以绑定一个记录当前滚动位置的函数,然后在每次endRequest后重新应用它。可能是这样的:
// Wrap everything up for tidiness' sake
var FormHandlerProto = function() {
var Me = this;
this.lastScrollPos = 0;
this.SetupForm = function() {
// Bind a function to the form's scroll container
$("#ContainerId").bind("scroll", function() {
// Record the scroll position
Me.lastScrollPos = $(this).scrollTop();
});
}
this.ScrollForm = function() {
// Apply the last scroll position
$("#ContainerId").scrollTop(Me.lastScrollPos);
}
this.EndRequestHandler = function(sender, args) {
if (args.get_error() != undefined)
Me.ScrollForm();
}
}
}
var FormHandler = new FormHandlerProto();
FormHandler.Setup(); // This assumes your scroll container doesn't get updated on postback. If it does, you'll want to call it in the EndRequestHandler.
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(FormHandler.EndRequestHandler);
只需将计时器控件放在内容模板中即可
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Interval="5000" OnTick="Timer1_Tick">
</asp:Timer>
<asp:ImageButton ID="ImageButton1" runat="server" Height="350" Width="700" />
</ContentTemplate>
</asp:UpdatePanel>
非常感谢您的代码!你真的让我走上了正轨。我不得不做一些MOD来让它工作,但我做到了。我将编辑我的问题以包含最终解决方案。再次感谢!我知道这是一个老帖子,但谢谢你!上面的“3月7日更新”对meThis有效最初对我有效,然后它停止了。。。我不知道发生了什么事。它很早就运行了,我不断发现“Sys”是未定义的。在页面生命周期中,这应该放在哪里?很难说没有看到您的项目,但您的脚本可能是在ASP.NET Ajax ScriptResource加载之前运行的。在我在应用程序中使用它的项目中,javascript加载在主体中(不理想,但由于外部约束,这是必需的)。最初,尝试将脚本主体移动到页面中的其他位置,或者尝试使用jquery从document.ready中加载它。作为一个合适的解决方案,可能值得考虑使用ScriptManager来管理您的脚本依赖关系。3月7日的更新为我做到了这一点!简单干净。