2009-01-27 12 views
22

Pracuję nad projektem w MVC i lubiłem się uczyć. Jest kilka narastających bólów, ale kiedy je odkryjesz, nie jest źle. Jedną rzeczą, która jest naprawdę prosta w świecie WebForms jest utrzymanie pozycji przewijania na stronie. Wszystko, co musisz zrobić, to ustawić właściwość MaintainScrollPositionOnPostback na true. Jednak w MVC nie używam postów, więc to nie zadziała dla mnie. Jaki jest standardowy sposób postępowania z tym?Jak utrzymać pozycję przewijania w MVC?

Edytuj: Ajax jest do zaakceptowania, ale zastanawiałem się też, jak to zrobić bez AJAX.

+0

Jeśli używasz AJAX i jQuery następnie wybrać widoczny element, który jest najwyższy na swojej stronie. Powiedzmy, że jest to kotwica bez tekstu Następnie w twoim $ (document) .ready write $ ('# pageTop'). Focus(); –

Odpowiedz

8

The sposób MaintainScrollPositionOnPostback działa jest to, że ma parę ukrytych pól: __SCROLLPOSITIONX i __SCROLLPOSITIONY

Na odświeżenie strony, ustawia nich

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; 
    } 

a następnie wywołuje 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; 
} 

Ale jak większość ludzi powiedziała, MVC powinno i tak unikać zwrotów.

+0

Humph! Nie mogę wymyślić, jak to edytować, aby ładnie umieścić próbkę kodu - czy ktoś chce mi powiedzieć, że jestem głupi? –

2

Moje własne obejście wykorzystuje pewne informacje w ViewData poznać obszar musi być pokazany w backnavigation i trochę javascript, aby umieścić kursor dla strony:

w widoku, element takiego:

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

a JavaScript, żeby repositionate strony:

<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> 

można użyć do określenia, co switch element ze strony widoku musisz przenieść.

Mam nadzieję, że to pomaga.

+0

To nie zachowuje dokładnej lokalizacji, takiej jak Web Forms. –

6

Właściwie nie istnieje standardowy sposób postępowania z tym, że był to Microsoft włamać się do wspierania ich post Powrót model. Potrzebowali tego, ponieważ każdy element sterujący odesłał wpis, a użytkownik był nieustannie przesuwany z powrotem na górę strony.

Zalecenie do użycia z MVC jest zrobić większość swojego posta z powrotem do serwerów wykorzystujących AJAX. Aby strona nie musiała się ponownie wyświetlać, fokus nie jest przenoszony. jQuery AJAX sprawia, że ​​naprawdę łatwe, i nie ma nawet standardowe formularze, takie jak

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

Który zadba o boku AJAX rzeczy dla Ciebie.

0

bardzo nie-dobry sposób, aby to zrobić jest za pomocą plików cookie.

Jeśli korzystasz z JEDNEJ strony w MVC, która obsługuje inne strony, możesz użyć fragmentu kodu, który ładuje każdą stronę, która tworzy ciasteczko (jeśli nie istnieje) o nazwie "scrolltop". Istnieją sposoby, aby javascript automatycznie aktualizował ten plik cookie, gdy użytkownik przewija w górę lub w dół, przechwytując te zdarzenia lub oglądając wartość przewijania.

Na nowej stronie wystarczy wczytać zapisaną pozycję i spowodować przewinięcie widoku w czasie 0 milisekund (przy pomocy Mootools lub dowolnego skryptu Ajax powinno to być możliwe), a użytkownik będzie dokładnie tam, gdzie był.

nie wiem zbyt wiele o ASP, więc nie wiem, czy istnieje sposób, aby zakotwiczyć do aktualnej pozycji y. JavaScript to szybki i łatwy sposób. Zakotwiczenia w HTMl mogą być opcją, jeśli każdy element zakotwiczony i zakotwiczony na innych stronach.

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

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

Użyłem atrybutów nazw w tagach. Nie używano javascript.

Strona, którą chcę zwrócić, zawierała <znaczniki> z atrybutem nazwy, np. < a nazwa = "testname" >.

strony (widok) Wróciłem z używanych tag < a href = "<%: Request.UrlReferrer% > #testname" > Powrót </a >” Request.UrlReferrer jest używany, aby przejść do poprzedniej strony. #testname przewija stronę, aby oznaczyć pozycję o nazwie „testname”.

1

Oto prosty, czysty roztwór Javascript która Przetestowałem w FF4 i IE9 tylko.

Chodzi o to, że to rozwiązanie powinno pogorszyć wdziękiem przez wracając do standardowych tagów #anchor na stronie. ing zastępuje zmienne #anchor za pomocą współrzędnych X i Y, a po załadowaniu po prostu odczytuję te wartości z kwerendy i przewijam je. Jeśli to się nie powiedzie z jakiegoś powodu, przeglądarka powinna nadal poruszać się w pozycji #anchor ...

Markup:

<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); 
    }); 
}); 
} 

Kilka metod pomocniczych:

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]; 
} 

To pasuje do moich potrzeb, ale może być bardziej ogólne/wielokrotnego użytku - Byłbym szczęśliwy ktoś poprawić ten ... :-)

4

wzorując WebForms i odpowiedź dostarczoną przez Richarda Gadsden, innego podejścia z wykorzystaniem JavaScript i zbieranie formularz może wyglądać mniej więcej tak:

@{ 
    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); 
}); 

Kod pod warunkiem, że jest inspiracją i nie jest w żaden sposób udoskonalona. Prawdopodobnie można to zrobić na kilka różnych sposobów, domyślam się, że wszystko sprowadza się do tego, w jaki sposób zdecydujesz się utrzymać wartość scrollTop dokumentu przez POST. Jest w pełni funkcjonalny i powinien być bezpieczny w przeglądarkach, ponieważ używamy jQuery do przewijania. Uważam, że podany kod jest oczywisty, ale z przyjemnością przedstawię bardziej szczegółowy opis tego, co się dzieje, daj mi znać.

+0

Dziękuję, to działało dobrze dla mnie przy minimalnym wysiłku! – Kon

+0

Jeszcze raz dziękuję ode mnie. Umieściłem ostatnie 3 linie w mojej sekcji $ (document) .ready() i wszystko działało świetnie. – Rocklan

26

mam rozwiązany to w JS:

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

Następnie w dokument gotowy:

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

Bardzo dobry. Podczas korzystania z silnika routingu, takiego jak asp.net mvc, strona w pamięci lokalnej może nie pasować, ale naprawdę nie jest potrzebna, jeśli używasz unikatowej nazwy dla lokalnej wartości przewijania pamięci ... $ (dokument) .scroll (function() { localStorage ['mójuniquename'] = $ (dokument) .scrollTop(); }); $ (dokument) .ready (function() { $ (dokument) .scrollTop (localStorage ['myuniquename']); }); – tintyethan

+0

Używałem tego w moich aplikacjach asp.net, ale teraz, kiedy używam MVC4, po prostu nie chce już pracować. Moment i kwota, którą przewija w dół, wydaje się taka przypadkowa. Nie mam pojęcia, co się dzieje. Wprowadzam breakpointy i widzę, że robi to "scrollTop (166)", ale przeglądarka po prostu go ignoruje, innym razem działa dobrze, a czasami przewija tylko trochę tego, co powinno. –

+0

Właśnie próbowałem projektu internetowego MVC4. To działa. Może jest konflikt skryptu lub w zależności od przeglądarki.Dodałem fragment po '@ Scripts.Render (" ~/bundles/jquery ")' – Madagaga

0

używam .scrollTop jak pokazano poniżej, bardzo łatwe, nawet współpracuje z wielu form w widok (Mam bardzo długi widok, z podziałem na wiele formularzy):

Najpierw włóż tę właściwość do modelu:

   public string scrollTop { get; set; } 

A w widoku, w środku Kształt # 1:

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

wewnątrz Postać 2:

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

wewnątrz Postać 2:

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

a następnie w u dołu widoku:

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

Twoja pozycja przewijania jest zawsze zachowywana po odświeżeniu, ponieważ pola @Html.HiddenFor przechowują aktualny zwój i przekazują go do modelu w poście. A potem, gdy strona pojawi się, pobiera wartość scrollTop z modelu. Pod koniec strona zachowa się jak formularz internetowy, wszystko pozostanie nienaruszone.

-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>

Można to wykorzystać, aby utrzymać stanowisko przewijania po odświeżenie strony.

Źródło: http://www.aspsnippets.com/Articles/Maintain-Scroll-Position-of-DIV-on-PostBack-in-ASPNet.aspx