Asp.net 如何避免在AutoPostBack上滚动UpdatePanel?

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中尝试了各种方法,包括: 页面加载 添加初始化请求 添加请

我在updatepanel中有一个ASP.NET FormView。我通过为FormView中的每个项设置AutoPostBack=true来自动保存表单

这意味着用户可以快速连续单击几个元素,并几乎同时启动几个异步回发

我遇到的问题是,当异步回发尚未完成时,用户能够继续向下滚动表单。浏览器总是滚动回第一次回发时的位置

Page.MaintainScrollPositionOnPostback设置为False

我在ajax和jquery中尝试了各种方法,包括:

  • 页面加载
  • 添加初始化请求
  • 添加请求
  • 准备好了吗
  • 等等
但我似乎总是只能访问第一次回发时的卷轴Y

回发完成后有没有办法检索当前的滚动Y,这样我就可以停止滚动了?或者,是否可以禁用滚动行为

谢谢


更新

多亏了@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日的更新为我做到了这一点!简单干净。