Comment maintenir la position scroll dans MVC?

je travaille sur un projet à MVC et j'ai aimé en apprendre davantage à ce sujet. Il ya quelques douleurs de croissance, mais une fois que vous comprenez qu'ils ne sont pas mauvais. Une chose qui est vraiment simple dans le monde des formulaires Web est de maintenir la position de défilement sur une page. Tout ce que vous faites est de définir la propriété MaintainScrollPositionOnPostback à true. Cependant, dans MVC, je n'utilise pas de postbacks donc cela ne fonctionnera pas pour moi. Quelle est la manière standard de gérer cela?

Edit: Ajax est acceptable, mais je me demandais aussi comment vous feriez sans AJAX.

24
demandé sur Papa Burgundy 2009-01-27 20:53:24
la source

11 ответов

la façon dont MaintainScrollPositionOnPostback fonctionne est qu'il a une paire de champs cachés: __SCROLLPOSITIONX et _ _ SCROLLPOSITIONY

Sur une publication, il définit ces,

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

puis il appelle 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;
}

mais comme la plupart des gens l'ont dit, MVC devrait éviter les postbacks de toute façon.

8
répondu Richard Gadsden 2009-02-04 20:49:40
la source

j'ai résolu ce problème en JS :

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

Puis dans le document prêt :

$(document).ready(function(){
    if (localStorage['page'] == document.URL) {
        $(document).scrollTop(localStorage['scrollTop']);
    }
});
32
répondu Madagaga 2015-01-22 14:08:13
la source

en fait, il n'y a pas de méthode standard pour gérer cela, C'était un hack de Microsoft pour supporter leur modèle post back. Ils avaient besoin de cela parce que chaque contrôle a fait un post en arrière et l'utilisateur serait constamment repoussé vers le haut de la page.

la recommandation pour l'utilisation avec MVC est de faire la plupart de votre post retour aux serveurs en utilisant AJAX. Afin que la page n'a pas alors rendre à nouveau l'accent n'est pas déplacé. jQuery rend AJAX vraiment facile, et il y a même des formes par défaut comme

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

qui s'occupera du côté AJAX des choses pour vous.

6
répondu Nick Berardi 2009-01-27 21:20:02
la source

en s'inspirant des formulaires Web et de la réponse fournie par Richard Gadsden, une autre approche utilisant javascript et la collection de formulaires pourrait ressembler à quelque chose comme ceci:

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

Le code fourni est pour l'inspiration et n'est en aucune façon embellie. Cela pourrait probablement être fait de différentes façons, je suppose que tout se résume à la façon dont vous décidez de persister la valeur scrollTop de votre document à travers le POST. Il est pleinement opérationnel et devrait être cross browser sûr, puisque nous sommes utiliser jQuery pour faire le défilement. Je pense que le code fourni est explicite, mais je serai heureux de fournir une description plus détaillée de ce qui se passe, faites-le moi savoir.

4
répondu Sniffdk 2011-07-13 23:57:01
la source

ma propre solution utilise quelques informations dans le ViewData pour savoir quel secteur doit être indiqué dans le backnavigation, et un peu de javascript pour positionner le curseur:

Dans la Vue, un élément comme ceci:

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

et le javascript pour repositionner la page:

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

vous pourriez utiliser un switch pour déterminer quel élément de la page d'affichage vous devez déménager.

j'Espère que ça aide.

3
répondu mapache 2009-01-27 21:14:59
la source
<%
   if(!ViewData.ModelState.IsValid)
   {
%>
   window.location.hash = 'Error';
<%
   }
%>

 <a name="Error"></a>
2
répondu Mike Flynn 2010-06-15 08:36:30
la source

j'ai utilisé des attributs de nom dans les balises. Pas de javascript utilisé.

la page à laquelle je voulais retourner avait des balises avec l'attribut name, par exemple .

La page (vue), je suis retourné à partir de la balise Retour". Demande.UrlReferrer est utilisé pour aller à la page précédente. #testname effile la position de la page pour marquer avec le nom "testname".

1
répondu the1johan 2011-01-18 09:42:35
la source

Voici une solution Javascript pure et simple que j'AI testée en FF4 et IE9 seulement.

L'idée est que cette solution devrait se dégrader gracieusement par revenir à la norme #anchor mots sur une page. Ce que je fais, c'est remplacer ceux-là!--3 -- > tags à la volée avec les coordonnées X et Y, puis en charge, je lis simplement ces valeurs à partir du querystring et j'y défile. Si cela échoue pour une raison quelconque, le navigateur devrait toujours naviguer vers le #anchor position...

Syntaxe:

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

quelques méthodes d'aide:

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

Cela correspond à mes besoins, mais pourrait être plus générique et réutilisable - je serais heureux que quelqu'un à améliorer cette situation... : -)

1
répondu user744322 2012-11-22 22:10:25
la source

une très mauvaise façon de faire cela est d'utiliser des cookies.

si vous utilisez une page dans votre MVC qui gère les autres pages, vous pouvez y ajouter un extrait de code qui charge chaque page qui crée un cookie (s'il n'existe pas) appelé "scrolltop". Il y a des façons d'avoir javascript pour mettre à jour automatiquement ce cookie lorsque l'utilisateur défile vers le haut ou vers le bas en enregistrant ces événements ou en regardant la valeur scrollTop.

sur une nouvelle page vous avez juste à charger la position sauvegardée et faire le afficher défiler là en 0 millisecondes (avec Mootools ou tout script Ajax cela devrait être possible) et l'Utilisateur sera exactement où ils étaient.

Je ne sais pas grand chose sur asp donc je ne sais pas s'il existe une méthode pour ancrer à une position y actuelle. Javascript est un moyen rapide et facile. Les ancres en HTMl pourraient être une option si vous aviez chaque élément ancré et posté l'ancre à d'autres pages.

0
répondu xaddict 2009-01-27 21:25:04
la source

Je l'utilise .scrollTop comme montré ci-dessous, très facile, il fonctionne même avec plusieurs formes dans la vue (j'ai une vue très longue, décomposée en plusieurs formes):

mettez D'abord cette propriété dans le modèle:

               public string scrollTop { get; set; }

Et dans la vue, à l'intérieur de la Forme #1:

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

dans le Formulaire n ° 2:

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

dans le Formulaire n ° 2:

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

et puis, en bas de la vue:

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

Votre position de défilement est toujours préservée sur postback parce que le @Html.HiddenFor fields stockez votre rouleau courant et passez-le au modèle sur post. Et puis, quand la page s'il obtient le scrollTop valeur du modèle. À la fin de votre page se comporterait comme webform, tout reste intact.

0
répondu Yogi 2014-01-01 00:08:21
la source

@{

}

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

Vous pouvez utiliser ceci pour maintenir la position de défilement après postback.

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

-1
répondu John007 2016-06-30 12:55:29
la source