2009-01-27 29 views
22

我正在从事MVC项目的工作,并且很享受这方面的知识。有一些成长的痛苦,但一旦你发现它并不坏。 WebForms世界中一件非常简单的事情就是保持页面上的滚动位置。你所做的就是将MaintainScrollPositionOnPostback属性设置为true。但是,在MVC中,我不使用回发,所以这不适用于我。处理这个问题的标准方法是什么?如何在MVC中保持滚动位置?

编辑︰阿贾克斯是可以接受的,但我也想知道你会怎么做没有AJAX。

+0

如果您正在使用AJAX和jQuery然后选择最上面的是你的页面上的可见元素。说它是一个没有文字的锚点然后在你的$(document).ready中写入$('#pageTop')。focus(); – 2013-10-24 11:52:13

回答

8

方式MaintainScrollPositionOnPostback工作原理是,它有一对隐藏字段: __SCROLLPOSITIONX和__SCROLLPOSITIONY

在回发,它集这些,

function WebForm_GetScrollY() { 
if (__nonMSDOMBrowser) { 
    return window.pageYOffset; 
} 
else { 
    if (document.documentElement && document.documentElement.scrollTop) { 
     return document.documentElement.scrollTop; 
    } 
    else if (document.body) { 
     return document.body.scrollTop; 
    } 
} 
return 0; 
} 
function WebForm_SaveScrollPositionSubmit() { 
    if (__nonMSDOMBrowser) { 
     theForm.elements['__SCROLLPOSITIONY'].value = window.pageYOffset; 
     theForm.elements['__SCROLLPOSITIONX'].value = window.pageXOffset; 
    } 
    else { 
     theForm.__SCROLLPOSITIONX.value = WebForm_GetScrollX(); 
     theForm.__SCROLLPOSITIONY.value = WebForm_GetScrollY(); 
    } 
    if ((typeof(this.oldSubmit) != "undefined") && (this.oldSubmit != null)) { 
     return this.oldSubmit(); 
    } 
    return true; 
    } 

然后调用RestoreScrollPosition:

function WebForm_RestoreScrollPosition() { 
    if (__nonMSDOMBrowser) { 
     window.scrollTo(theForm.elements['__SCROLLPOSITIONX'].value, theForm.elements['__SCROLLPOSITIONY'].value); 
    } 
    else { 
     window.scrollTo(theForm.__SCROLLPOSITIONX.value, theForm.__SCROLLPOSITIONY.value); 
    } 
    if ((typeof(theForm.oldOnLoad) != "undefined") && (theForm.oldOnLoad != null)) { 
     return theForm.oldOnLoad(); 
    } 
    return true; 
} 

但正如大多数人所说,MVC应该避免回发。

+0

哼!无法编辑好如何编辑这个代码示例 - 任何人想告诉我我是如何愚蠢? – 2009-02-04 17:52:47

2

我自己的解决方法是使用在ViewData一些信息知道必须在backnavigation显示什么区域,以及一些JavaScript来定位页面的光标:

在视图中,像这样的元素:

<h3 id="tasks"> 
    Contained tasks 
</h3> 

和JavaScript来repositionate页:

<script type="text/javascript"> 
    addOnLoad(goAnchor); 

    function goAnchor() { 
     var paging = <%= //Here you determine (from the ViewData or whatever) if you have to position the element %>; 
     if (paging == "True") { 
      window.location.hash = "tasks"; 
     } 
</script> 

你可以使用一个switch,以确定哪些元素来自您必须重新定位的视图页面。

希望它有帮助。

+0

这不会像Web窗体那样保留确切的位置。 – 2009-01-27 18:18:29

6

实际上没有处理这个问题的标准方式,这是一个微软黑客来支持他们的回发模式。他们需要这样做,因为每个控件都做了回传,用户会不断被推回到页面的顶部。

与MVC一起使用的建议是使用AJAX将大部分帖子发回服务器。这样页面不必重新渲染,焦点也不会移动。 jQuery使AJAX真的很容易,甚至有默认的形式,如

<% Ajax.BeginForm(...) %> 

这将负责照顾AJAX的一面。

0

一个非常不好的方法是使用cookie。

如果您在处理其他页面的MVC中使用了一个页面,您可以为其加载创建cookie(如果不存在)称为“scrolltop”的每个页面的代码片段。 当用户通过捕获这些事件或观看scrollTop值而向上或向下滚动时,有许多方法可让javascript自动更新此cookie。

在新的页面上,您只需加载保存的位置,并使视图在0毫秒内滚动(使用Mootools或任何Ajax脚本,这应该是可能的),用户将确切地位于他们所在的位置。

我不太了解asp,所以我不知道是否存在一种方法来锚定当前的y位置。 Javascript是一种快速简单的方法。如果您将每个元素都锚定并将锚点发布到其他页面,HTMl中的锚点可能是一个选项。

2
<% 
    if(!ViewData.ModelState.IsValid) 
    { 
%> 
    window.location.hash = 'Error'; 
<% 
    } 
%> 

<a name="Error"></a> 
1

我在标签中使用了名称属性。没有使用JavaScript。

我想返回的页面有<a>带有name属性的标签,例如< a name =“testname”>。

页(图)我是从旧标签< A HREF =回来了。 “<%:Request.UrlReferrer%> #testname” >回</A >” Request.UrlReferrer用来转到上一页。 #testname滚动页面位置与名称“测试名”标记。

1

这里有一个简单的,纯JavaScript的解决方案,我在FF4和IE9只测试过

的想法是,这个解决方案应该由优雅降级回到页面上的标准#anchor标签。我在做什么ing正在用X和Y坐标替换这些#anchor标签,然后在加载时,我只是从查询字符串中读取这些值并滚动到那里。如果由于某种原因失败,浏览器还是应该定位到#anchor位置...

标记:

<a href="/somecontroller/someaction/#someanchor">My Link</a> 

的jQuery:

$(function() { 

// RESTORE SCROLL POSITION 
RestoreScrollPosition(); 

// SAVE SCROLL POSITION 
$('a:not(a[href^="http"])').filter('[href$="#someanchor"]').each(function() { 
    $(this).click(function() { 
     var href = $(this).attr('href').replace("#someanchor",""); 
     if (href.indexOf('?') == -1) { 
      href = href + '?x=' 
     } else { 
      href = href + '&x=' 
     } 
     href = href + window.pageXOffset; 
     href = href + '&y=' + window.pageYOffset; 
     $(this).attr('href', href); 
    }); 
}); 
} 

的helper方法:

function RestoreScrollPosition() { 

    var scrollX = gup('x'); 
    var scrollY = gup('y'); 

    if (scrollX != null && scrollY != null) { 
     window.scrollTo(scrollX, scrollY); 
     return true; 
    } 
    return false; 
} 

function gup(name) { 
    name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); 
    var regexS = "[\\?&]" + name + "=([^&#]*)"; 
    var regex = new RegExp(regexS); 
    var results = regex.exec(window.location.href); 
    if (results == null) 
     return ""; 
    else 
     return results[1]; 
} 

这符合我的需求,但可能更通用/可重用 - 我很乐意有人以改善此... :-)

4

以从WebForms的灵感,由理查德·加兹登,使用JavaScript和形式收集可能是这个样子的另一种方法提供了答案:

@{ 
    var scrollPositionX = string.Empty;   
    if(IsPost) { 
     scrollPositionX = Request.Form["ScrollPositionX"]; 
    } 
} 

<form action="" method="post"> 
    <input type="hidden" id="ScrollPositionX" name="ScrollPositionX" value="@scrollPositionX" /> 
    <input type="submit" id="Submit" name="Submit" value="Go" /> 
</form> 

$("#Submit").click(function() { 
    $("#ScrollPositionX").val($(document).scrollTop()); 
}); 

$("#ScrollPositionX").each(function() { 
    var val = parseInt($(this).val(), 10); 
    if (!isNaN(val)) 
     $(document).scrollTop(val); 
}); 

代码提供的是灵感,并没有任何美化。它可能会以几种不同的方式完成,我想这一切都归结于您如何决定在整个POST中保留文档的scrollTop值。它完全正常工作,并且应该跨浏览器安全,因为我们使用jQuery来执行滚动操作。我相信所提供的代码是不言自明的,但我会很乐意提供关于发生了什么的更详细的描述,请让我知道。

+0

谢谢,这个工作对我来说很轻松! – Kon 2012-02-01 02:19:05

+0

额外感谢我的来信。我把最后3行放到我的$(document).ready()部分,并且这一切都很好。 – Rocklan 2012-11-19 23:01:10

26

我在JS解决了这个:

$(document).scroll(function(){ 
    localStorage['page'] = document.URL; 
    localStorage['scrollTop'] = $(document).scrollTop(); 
}); 

然后在文件准备:

$(document).ready(function(){ 
    if (localStorage['page'] == document.URL) { 
     $(document).scrollTop(localStorage['scrollTop']); 
    } 
}); 
0

我用.scrollTop如下图所示,很容易的,它甚至在多种形式的作品查看(我有很长的视野,分解成多种形式):

首先把这个属性放在模型里面:

   public string scrollTop { get; set; } 

并在视图中,形式#1内:

   @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm1"}) 

内表#2:

   @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm2"}) 

内表#2:

   @Html.HiddenFor(m => m.scrollTop, new {@id="ScrollForm3"}) 

,然后在底部视图:

$(document).ready(function() { 
    $(document).scrollTop(@Model.scrollTop); 
    $(document).scroll(function() { 
     $("#ScrollForm1").val($(document).scrollTop()); 
     $("#ScrollForm2").val($(document).scrollTop()); 
     $("#ScrollForm3").val($(document).scrollTop()); 
     }); 
    }); 

回滚后,您的滚动位置始终保留,因为@ Html.HiddenFor字段会存储当前滚动并将其传递给模型。然后,当页面出现时,它会从模型中获取scrollTop值。最后你的页面会像webform一样,一切都保持不变。

-1

@{ 
 

 
} 
 

 
<html> 
 

 
<head> 
 
    <script type="text/javascript"> 
 

 
window.onload = function() { 
 
    var div = document.getElementById("dvScroll"); 
 
    var div_position = document.getElementById("div_position"); 
 
    var position = parseInt(@Request.Form("div_position")); 
 
    if (isNaN(position)) { 
 
     position = 0; 
 
    } 
 

 
    div.scrollTop = position; 
 
    div.onscroll = function() { 
 
     div_position.value = div.scrollTop; 
 
    }; 
 
}; 
 

 
</script> 
 
</head> 
 

 
<body> 
 

 
<div id="dvScroll" style="overflow-y: scroll; height: 260px; width: 300px"> 
 

 
    1. This is a sample text 
 

 
    <br /> 
 

 
    2. This is a sample text 
 

 
    <br /> 
 

 
    3. This is a sample text 
 

 
    <br /> 
 

 
    4. This is a sample text 
 

 
    <br /> 
 

 
    5. This is a sample text 
 

 
    <br /> 
 

 
    6. This is a sample text 
 

 
    <br /> 
 

 
    7. This is a sample text 
 

 
    <br /> 
 

 
    8. This is a sample text 
 

 
    <br /> 
 

 
    9. This is a sample text 
 

 
    <br /> 
 

 
    10. This is a sample text 
 

 
    <br /> 
 

 
    11. This is a sample text 
 

 
    <br /> 
 

 
    12. This is a sample text 
 

 
    <br /> 
 

 
    13. This is a sample text 
 

 
    <br /> 
 

 
    14. This is a sample text 
 

 
    <br /> 
 

 
    15. This is a sample text 
 

 
    <br /> 
 

 
    16. This is a sample text 
 

 
    <br /> 
 

 
    17. This is a sample text 
 

 
    <br /> 
 

 
    18. This is a sample text 
 

 
    <br /> 
 

 
    19. This is a sample text 
 

 
    <br /> 
 

 
    20. This is a sample text 
 

 
    <br /> 
 

 
    21. This is a sample text 
 

 
    <br /> 
 

 
    22. This is a sample text 
 

 
    <br /> 
 

 
    23. This is a sample text 
 

 
    <br /> 
 

 
    24. This is a sample text 
 

 
    <br /> 
 

 
    25. This is a sample text 
 

 
    <br /> 
 

 
</div> 
 

 
<hr /> 
 
<form method="post"> 
 
<input type="hidden" id="div_position" name="div_position" /> 
 
<input type="submit" value="Cool" /> 
 
    </form> 
 
</body> 
 
</html>

您可以用它来保持回发后滚动位置。

来源:http://www.aspsnippets.com/Articles/Maintain-Scroll-Position-of-DIV-on-PostBack-in-ASPNet.aspx