我正在研究MVC中的一个项目并且很高兴能够学习它。有一些成长的痛苦,但一旦你弄清楚它并不坏。 WebForms世界中一件非常简单的事情就是保持页面上的滚动位置。您所做的只是将MaintainScrollPositionOnPostback属性设置为true。但是,在MVC中,我没有使用回发,所以这对我不起作用。处理此问题的标准方法是什么?
编辑: Ajax是可以接受的,但我也想知道如果没有AJAX你会怎么做。
答案 0 :(得分:37)
我在JS中解决了这个问题:
$(document).scroll(function(){
localStorage['page'] = document.URL;
localStorage['scrollTop'] = $(document).scrollTop();
});
然后在文件准备中:
$(document).ready(function(){
if (localStorage['page'] == document.URL) {
$(document).scrollTop(localStorage['scrollTop']);
}
});
答案 1 :(得分: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应该避免回发。
答案 2 :(得分:6)
实际上没有标准的处理方法,这是微软支持他们的回发模式。他们需要这个,因为每个控件都会发回一个帖子,用户会不断被推回到页面顶部。
与MVC一起使用的建议是使用AJAX将大部分回发到服务器。这样页面就不必重新渲染焦点就不会移动。 jQuery使AJAX非常简单,甚至还有默认表单,如
<% Ajax.BeginForm(...) %>
将为您处理AJAX方面的问题。
答案 3 :(得分:4)
从WebForms和Richard Gadsden提供的答案中获取灵感,使用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进行滚动。我相信所提供的代码是不言自明的,但我很乐意提供有关最新情况的详细说明,请告诉我。
答案 4 :(得分:3)
我自己的解决方法是使用ViewData
中的一些信息来了解必须在backnavigation中显示哪些区域,并使用一些小的javascript来定位页面的光标:
在视图中,这样的元素:
<h3 id="tasks">
Contained tasks
</h3>
用于重新定位页面的javascript:
<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
来确定您必须重新定位的视图页面中的哪个元素。
希望它有所帮助。
答案 5 :(得分:2)
<%
if(!ViewData.ModelState.IsValid)
{
%>
window.location.hash = 'Error';
<%
}
%>
<a name="Error"></a>
答案 6 :(得分:1)
我在标签中使用了名称属性。没有使用javascript。
我想要返回的页面有&lt; a&gt;具有名称属性的标签,例如&lt; a name =“testname”&gt;。
我从旧标签&lt; a href =“&lt;%:Request.UrlReferrer%&gt; #testname”&gt;返回&lt; / a&gt;“返回的页面(视图)。 Request.UrlReferrer用于转到上一页。 #testname将页面位置滚动到标记为“testname”的标记。
答案 7 :(得分:1)
这是一个简单,纯粹的Javascript解决方案,我只在FF4和IE9中测试过。
这个想法是,这个解决方案应该通过回退到页面上的标准#anchor
标记来优雅地降级。我正在做的是用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);
});
});
}
一些辅助方法:
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];
}
这符合我的需求,但可能更通用/可重复使用 - 我很乐意有人改进这个......: - )
答案 8 :(得分:0)
一个非常不好的方法是使用cookie。
如果你在MVC中使用一个处理其他页面的页面,你可以使用一个代码片段来加载每个创建一个名为“scrolltop”的cookie(如果不存在)的页面。 当用户通过捕获这些事件或观看scrollTop值向上或向下滚动时,有一些方法可以让javascript自动更新此cookie。
在新页面上,您只需加载保存的位置并使视图在0毫秒内滚动(使用Mootools或任何Ajax脚本,这应该是可能的),用户将完全放在原来的位置。
我对asp知之甚少,所以我不知道是否存在锚定到当前y位置的方法。 Javascript是一种快速简便的方法。如果您将每个元素锚定并将锚点发布到其他页面,则HTMl中的锚点可以是一个选项。
答案 9 :(得分: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一样,一切都保持不变。
答案 10 :(得分:0)
10年后,采用了另一种JS解决方案。另一个JS解决方案等待页面滚动,并在页面加载时滚动到保存的任何位置。对于大多数人来说,这很好(尽管它不会删除值,所以当您查看该页面时,页面将始终滚动到该位置...)。我的解决方案是等待表单提交:
(是的,它使用的是jQuery,但是该网站上有很多...)
$(document).ready(function() {
var $form = $('#title_form');
var root = $('#url_root').val();
var php_file = 'assets/ajax/update.php';
var url = root + php_file;
$('#project_title').on('change', function() {
$form.trigger('submit');
});
$form.on('submit', function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: url,
data: $(this).serialize(),
success: function(response) {
var jsonData = JSON.parse(response);
console.log(jsonData);
}
});
});
});
这将滚动回到表单的顶部,这样,当您滚动到验证摘要之外时,所有错误消息都将可见。
答案 11 :(得分:-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>
&#13;
您可以使用此功能在回发后保持滚动位置。
来源:http://www.aspsnippets.com/Articles/Maintain-Scroll-Position-of-DIV-on-PostBack-in-ASPNet.aspx