it-swarm.com.de

WinRT/UWP Frame- und Page-Caching: So erstellen Sie eine neue Seiteninstanz in Navigate () und behalten die Seiteninstanz in GoBack ()

Ich versuche, eine UWP-Anwendung (Universal Windows App) mit C # zu erstellen. Mein Problem ist das Frame-Steuerelement: Wenn ich es ohne NavigationCacheMode = Required verwende, wird die Seite jedes Mal, wenn der Benutzer zurückkehrt, nicht im Speicher gehalten und neu erstellt. Wenn ich NavigationCacheMode auf Required oder Enabled setze, funktioniert das Zurückgehen ordnungsgemäß (kein neues Seitenobjekt) aber Wenn ich zu einer anderen Seite desselben Typs navigiere, wird das vorherige Seitenobjekt wiederverwendet und wiederverwendet (keine neue Seiteninstanz). 

Gewünschtes Verhalten:

Gibt es eine Möglichkeit, mit dem ursprünglichen Frame-Steuerelement (wie in Windows Phone) folgendes Verhalten zu erzielen: 

  1. Neue Seiteninstanz auf Navigate() erstellen
  2. Behalten Sie die Seiteninstanz auf GoBack() 

Die einzige Lösung, die ich kenne, ist, eine eigene Frame-Steuerung zu erstellen. Dies führt jedoch zu anderen Problemen (z. B. fehlende SetNavigationState()-Methode usw.).

Beispielszenario:

Einfaches Anwendungsbeispiel mit drei Seiten: TvShowListPage, TvShowDetailsPage, SeasonDetailsPage

  1. TvShowListPage ist die Einstiegsseite. Navigieren Sie nach dem Klicken auf eine TvShow zu TvShowDetailsPage
  2. Wählen Sie nun in TvShowDetailsPage eine Saison in der Liste aus und navigieren Sie zur TvShowDetailsPage
  3. Wenn Sie zurück navigieren, sollten sich die Seiten im Speicher befinden, um ein erneutes Laden der Seiten zu vermeiden. 
  4. Wenn der Benutzer jedoch zu TvShowListPage zurückkehrt und eine andere TvShow auswählt, wird die TvShowDetailsPage recycelt und befindet sich möglicherweise in einem falschen Zustand (z. B. das Cast-Pivot anstelle des ersten, Saisons-Pivot).

Ich suche nach dem Standardverhalten von Windows Phone 7: Beim Navigieren wird eine neue Seite auf dem Seitenstapel erstellt. Beim Zurückgehen wird die oberste Seite aus dem Stapel entfernt und die vorherige Seite aus dem Stapel angezeigt (im Speicher gespeichert). 

Lösung:

Da es keine Lösung für dieses Problem gab, musste ich alle pagingrelevanten Klassen neu implementieren: Page, Frame, SuspensionManager usw. 

Die library MyToolkit, die alle diese Klassen enthält, kann hier heruntergeladen werden: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview

Verweise:

45
Rico Suter

Da es keine Lösung für dieses Problem gab, musste ich alle pagingrelevanten Klassen neu implementieren: Page, Frame, SuspensionManager usw. 

Die Lösung kann hier heruntergeladen werden: https://github.com/MyToolkit/MyToolkit/wiki/Paging-Overview

Update:

Die Seitenklasse enthält jetzt auch die Methode OnNavigatingFromAsync, um beispielsweise ein asynchrones Popup-Fenster anzuzeigen und die Navigation abzubrechen, falls erforderlich ...

16
Rico Suter

Ich hatte das gleiche Problem. Ich wollte es so, dass ich eine neue Instanz erstellen würde, wenn ich in Metro (Windows Store richtig) vorankomme. Beim Zurückgehen bleiben jedoch die Daten, die ich wollte, erhalten.

Also habe ich ebenfalls NavigationCacheMode = NavigationCacheMode.Enabled verwendet. Ich stellte fest, dass unabhängig davon, auf welchem ​​Weg ich vorwärts oder rückwärts fuhr, immer alles gerettet wurde. Ich würde also einige Seiten weitergehen und dann ein paar Schritte zurückgehen. In der Hoffnung, dass alles zurückgesetzt wurde, als ich mich vorwärts bewegte, stellte ich fest, dass dies nicht der Fall war. es hatte die Daten behalten.

Ich habe alles ausprobiert, einschließlich des Schreibens meines eigenen Schaltflächencodes, um NavigationCacheMode = NavigationCacheMode.Disabled einzuschließen, jedoch ohne Erfolg. Wie andere bereits erwähnt haben, wird der NavigationCacheMode nach der Aktivierung einfach nicht deaktiviert.

Ich habe eine Lösung gefunden. Ich ging zu LayoutAwarePage.cs und nahm einfach eine kleine Änderung vor. Unter dem "OnNavigatedTo" fand ich die Zeile:

// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null) return;

Der Kommentar lief jedoch gegen das, was ich wollte. Ich suchte Zustandsladen in einem unidirektionalen Muster. Wenn ich mich vorwärts bewege, wollte ich Zustandsladen; Wenn ich mich rückwärts bewege, wollte ich, dass das Verhalten den Kommentar angibt - es wird kein Status geladen.

Also habe ich einfach die Zeile geändert.

// Returning to a cached page through navigation shouldn't trigger state loading
if (this._pageKey != null && e.NavigationMode == NavigationMode.Back) return;

Ich habe es getestet und es funktioniert perfekt. Wenn Sie nun rückwärts navigieren, merkt es sich den Zustand und behält die Seite bei. Wenn Sie vorwärts navigieren, wird es frisch geladen.

Vielleicht nicht die beste Methode, aber ich nenne nicht "OnNavigatedTo" von meinem Code-Behind. Ich mache alles über den "LoadState". Wenn Sie "OnNavigatedTo" im Code-Behind überschreiben, sehen Sie möglicherweise ein anderes Verhalten.

Vielen Dank,

Joseph Irvine

8
jkeagle13

Wenn Sie durch forward navigieren, können Sie NavigationCacheMode auf Disabled setzen, bevor Sie Frame.Navigate aufrufen? Dann in OnNavigatedTo () set NavigationCacheMode zurück zu Enabled .

Dies sollte dazu führen, dass die Zwischenspeicherung deaktiviert wird, wenn Sie vorwärts navigieren. Wenn Sie jedoch auf der neuen Seiteninstanz ankommen, würde OnNavigatedTo es wieder aktivieren. Wenn Sie zurück navigieren möchten, berühren Sie den NavigationCacheMode nicht, bevor Sie Frame.GoBack aufrufen. Das sollte Ihnen die zwischengespeicherte Instanz geben, denke ich.

Ich glaube, das würde funktionieren, aber ich habe es nicht getestet. Ich wäre neugierig zu wissen, ob das stimmt. Interessantes Szenario dort. Ich würde gerne die App in Aktion sehen und die Verwendung dieses Verhaltens besser verstehen.

6

Mit der Eigenschaft NavigationCacheMode können Sie angeben, ob für jeden Besuch der Seite eine neue Instanz der Seite erstellt wird oder ob für jeden Besuch eine zuvor erstellte Instanz der im Cache gespeicherten Seite verwendet wird.

Der Standardwert für die NavigationCacheMode-Eigenschaft lautet Disabled. Setzen Sie die NavigationCacheMode-Eigenschaft auf Enabled oder Required, wenn eine neue Instanz der Seite für jeden Besuch nicht unbedingt erforderlich ist. Durch die Verwendung einer zwischengespeicherten Instanz der Seite können Sie die Leistung Ihrer Anwendung verbessern und die Belastung Ihres Servers reduzieren.

Wenn Sie NavigationCacheMode auf Required setzen, bedeutet dies, dass die Seite unabhängig von der Anzahl der in der CacheSize-Eigenschaft angegebenen Anzahl zwischengespeicherter Seiten zwischengespeichert wird. Als Erforderlich gekennzeichnete Seiten werden nicht für die Gesamtsumme von CacheSize berücksichtigt. Wenn Sie NavigationCacheMode auf Enabled setzen, wird die Seite zwischengespeichert. Sie steht jedoch zur Verfügung, wenn die Anzahl der zwischengespeicherten Seiten den Wert von CacheSize überschreitet.

Setzen Sie die NavigationCacheMode-Eigenschaft auf Disabled, wenn für jeden Besuch eine neue Instanz erstellt werden muss. Beispielsweise sollten Sie keine Seite zwischenspeichern, die Informationen enthält, die für jeden Kunden eindeutig sind.

Die OnNavigatedTo-Methode wird für jede Anforderung aufgerufen, auch wenn die Seite aus dem Cache abgerufen wird. Sie sollten in diese Methode Code einschließen, der für jede Anforderung ausgeführt werden muss, anstatt diesen Code im Page-Konstruktor zu platzieren.

2
Magi

Ich habe dies erreicht durch:

  • Festlegen von NavigationCacheMode für erforderliche Seiten auf Erforderlich/Aktiviert.
  • Klicken Sie auf den Button/Link auf Seite2:

    Durchlaufen Sie den Frame BackStack und stellen Sie fest, ob sich die Seite 2 in BackStack befindet. Wenn Seite2 gefunden wird, rufen Sie Frame.GoBack () häufig auf. Wenn nicht gefunden, navigieren Sie einfach zur neuen Seite. Dies funktioniert für alle Seiten.

Code-Beispiel:

public void Page2Clicked(object sender, RoutedEventArgs e)
{
int isPresent = 0;
int frameCount = 0;
//traverse BackStack in reverse order as the last element is latest page
for(int index= Frame.BackStack.Count-1; index>=0;index--)
{
    frameCount += 1;
    //lets say the first page name is page1 which is cached
    if ("Page2".Equals(Frame.BackStack[index].SourcePageType.Name))
    {
        isPresent = 1;
        //Go back required no of times
        while (frameCount >0)
        {
            Frame.GoBack();
            frameCount -= 1;
        }
        break;
    }

}
    if (isPresent == 0)
    {
    Frame.Content = null;
    Frame.Navigate(typeof(Page2));
    }
}

Dies ist hilfreich, wenn für die Vorwärts-/Rückwärts-Tasten nicht viel von . Verwendet wird, da sich diese Lösung auf die Vorwärts-/Rückwärtsnavigation auswirkt .__ Wenn Sie auch die Vorwärts-/Rückwärtsnavigation verwenden möchten, einige zusätzliche Fälle muss gehandhabt werden.

0
Mithilesh Gupta

Ich musste eine page2-Klasse von meiner page-Klasse ableiten. Wenn ich dann zu einer zweiten Version derselben Seite navigieren möchte, erkenne ich, ob das this-Objekt page oder page2 ist. Ich navigiere dann zu page2, wenn ich in page war, und navigiere zu page, wenn in page2.

Der einzige Nachteil, der sehr groß ist, besteht darin, dass es keine Möglichkeit gibt, eine XAML-Datei von einer anderen abzuleiten. Daher befindet sich der gesamte C # -Code wie erwartet in der page-Klasse, aber es gibt zwei nahezu identische XAML-Dateien, eine für jede Version der Seite.

Ein kleines Skript könnte möglicherweise als Vorbereitungsschritt hinzugefügt werden, um die zweite Seitenklasse aus der ersten zu generieren, die XAML-Daten zu kopieren und die Klassennamen anzupassen.

Es ist hässlich, aber es funktioniert fast perfekt und ich muss mich nie um C # -Code-Duplizierung oder seltsame Navigations-Cache-Probleme kümmern. Am Ende habe ich nur noch doppelten XMAL-Code, der sich in meinem Fall sowieso nie ändert. Am Ende bekomme ich zwei Warnungen, dass das new-Schlüsselwort für den automatisch generierten Code für page2.InitializeComponent() und page2.Connect() nicht verwendet wird.

Interessanterweise führt das Navigieren zu page, dann zu page2 und dann zu page zu keinen Problemen, und die zweite Instanz der page-Klasse ist eine tatsächliche zweite Instanz, die nicht mit der ersten zusammenhängt.

Beachten Sie, dass diese Lösung wahrscheinlich von MS empfohlen wird.

0
David Rector