2017-06-12 2 views
3

Das Projekt an dem ich arbeite enthält die folgende Struktur:Xamarin Forms MVVM Klare Navigation Stapel von INavigationService

Wenn App gestartet wird, Benutzer sieht eine Begrüßungsseite. Zu diesem Zeitpunkt hat der Benutzer zwei Optionen. Sie können sich entweder anmelden oder registrieren. Wenn angemeldet == true; dann gehen Sie zur Hauptdetailseite. Oder in der Registrierung, wenn register == Erfolg, gehen Sie dann zur Login-Seite und folgen Sie dem gleichen Prozess und auf der Master-Detailseite.

   -> Login Page     || 
Welcome Page >> ==================    || => MasterDetailPage 
       -> Register Page -> Login page || 

ich MVVM Licht bin mit meinem Navigationsstapel über INavigationService als meine UI und Geschäftslogik wird über MVVM getrennt zu behandeln. Alles funktioniert ziemlich gut, außer dass ich den Navigationsstapel zurücksetzen muss, damit der Benutzer nicht auf eine Seite zugreifen kann, bevor die "MasterDetailPage" oben angezeigt wurde. Im Moment können Benutzer zur Anmeldung oder Registrierung oder zu jeder anderen Seite zurückkehren, indem sie die Hardware-Zurück-Taste auf Android verwenden oder von der linken Seite auf iOS wischen. Außerdem gibt es eine Navigations-Zurück-Schaltfläche in der oberen Navigationsleiste. navigation bar example

Meine App.cs so etwas wie dieses

public App() 
{ 
    var nav = RegisterNavigationService(); 
    SimpleIoc.Default.Register<INavigationService>(() => nav); 

    InitializeComponent(); 

    var initialPage = new NavigationPage(new WelcomePage()); 
    nav.Initialize(initialPage); 
    MainPage = initialPage; 
} 

private NavigationService RegisterNavigationService() 
{ 
    var nav = new NavigationService(); 
    nav.Configure(Locator.LoginForm, typeof(LoginForm)); 
    nav.Configure(Locator.RegisterSuccessPage, typeof(RegisterSuccessPage)); 
    nav.Configure(Locator.RegistrationForm, typeof(RegistrationForm)); 
    nav.Configure(Locator.WelcomePage, typeof(WelcomePage)); 
    nav.Configure(Locator.MasterMainPage, typeof(MasterMainPage)); 
    return nav; 
} 

Auf meiner Ansicht Modelle sieht, Griff ich die Navigationsbefehle wie folgt aus:

public class LoginFormViewModel : BaseViewModel 
{ 
    private readonly INavigationService _navigationService; 
    public Command NavigateToMainPage { get; } 

    public LoginFormViewModel(INavigationService navigationService) 
    { 
     _navigationService = navigationService ?? throw new ArgumentNullException("navigationService"); 

     NavigateToMainPage = new Command(() => NavigateToMainApp()); 
    } 

    private void NavigateToMainApp() 
    { 
     _navigationService.NavigateTo(Locator.MasterMainPage); 
    } 
} 

Schließlich sieht meine NavigationService.cs so. .. Ich habe diesen Teil des Codes kaum berührt ... Das einzige, was ich ausprobiert habe, ist die 'ClearNavigationStack'-Methode, aber das war ein Fehler.

public class NavigationService : INavigationService, INavigationServiceExtensions 
{ 
    private Dictionary<string, Type> _pagesByKey = new Dictionary<string, Type>(); 
    private NavigationPage _navigation; 

    public string CurrentPageKey 
    { 
     get 
     { 
      lock (_pagesByKey) 
      { 
       if (_navigation.CurrentPage == null) 
       { 
        return null; 
       } 

       var pageType = _navigation.CurrentPage.GetType(); 

       return _pagesByKey.ContainsValue(pageType) 
        ? _pagesByKey.First(p => p.Value == pageType).Key 
        : null; 
      } 
     } 
    } 

    public void GoBack() 
    { 
     _navigation.PopAsync(); 
    } 

    public void NavigateTo(string pageKey) 
    { 
     NavigateTo(pageKey, null); 
    } 

    public void NavigateTo(string pageKey, object parameter) 
    { 
     lock (_pagesByKey) 
     { 
      if (_pagesByKey.ContainsKey(pageKey)) 
      { 
       ConstructorInfo constructor; 
       object[] parameters; 
       var type = _pagesByKey[pageKey]; 

       if (parameter == null) 
       { 
        constructor = type.GetTypeInfo() 
         .DeclaredConstructors 
         .FirstOrDefault(c => !c.GetParameters().Any()); 

        parameters = new object[] { }; 
       } 
       else 
       { 
        constructor = type.GetTypeInfo() 
         .DeclaredConstructors 
         .FirstOrDefault(
          c => 
          { 
           var p = c.GetParameters(); 
           return p.Count() == 1 
             && p[0].ParameterType == parameter.GetType(); 
          }); 

        parameters = new[] { parameter }; 
       } 

       if (constructor == null) 
       { 
        throw new InvalidOperationException("No suitable constructor found for page " + pageKey); 
       } 

       var page = constructor.Invoke(parameters) as Page; 
       _navigation.PushAsync(page); 
      } 
      else 
      { 
       throw new ArgumentException(
        string.Format("No such page: {0}. Did you forget to call NavigationService.Configure?", pageKey), "pageKey"); 
      } 
     } 
    } 

    public void Configure(string pageKey, Type pageType) 
    { 
     lock (_pagesByKey) 
     { 
      if (_pagesByKey.ContainsKey(pageKey)) 
      { 
       _pagesByKey[pageKey] = pageType; 
      } 
      else 
      { 
       _pagesByKey.Add(pageKey, pageType); 
      } 
     } 
    } 


    public void ClearNavigationStack() 
    { 
     lock (_pagesByKey) 
     { 
      foreach (var pageKey in _pagesByKey.Keys) 
      { 
       _pagesByKey.Remove(pageKey); 
      } 
     } 
    } 

    public void Initialize(NavigationPage navigation) 
    { 
     _navigation = navigation; 
    } 
} 

Ich habe dieses Stück aus der folgenden git Repo genommen: https://github.com/mallibone/MvvmLightNavigation.XamarinForms

dieses Tutorial folgenden: https://mallibone.com/post/xamarin.forms-navigation-with-mvvm-light

Hinweis: Es ist eine PCL ist.

Jeder Vorschlag ist willkommen, da ich die letzten 2 Tage hier war.

EDIT: Gerade jetzt, ich habe zu „verstecken“ dem nav-Stack verwaltet von meiner Mainpage zu so etwas wie diese Einstellung

App.Current.MainPage = new MasterMainPage(); 

Aber es scheint wie ein Code Geruch und sieht aus wie eine schreckliche Hack . Außerdem bin ich mir nicht sicher, ob es die Konzepte, denen ich folge, "verletzt" ... Und ich denke, dass dieser Navigationsstapel sowieso nie weg sein wird, da ich andere Navigationstapel innerhalb der Hauptdetailseiten machen werde.

Antwort

1

Von Ihrem Bild sehe ich, dass Sie Master/Detaied-Seite in Navigationsseite haben. Xamarin empfiehlt nicht, das zu tun. Ich weiß nicht, wie Sie es in MVVM Licht tun werden, aber in regelmäßigen Formen Sie Paar Optionen zu erreichen, was Sie wollen:

  1. Wenn Sie jemals Ihre Anmeldung müssen zurück gehen oder registrieren Seite, die Sie verwenden sollten

    await Navigation.PushModalAsync(new YourMasterDetailPage()); 
    

Dann können Sie popmodal ihnen zurück zu bekommen, aber in diesem Fall Hardware-Taste werden Sie noch zur Anmeldung bringen.Sie können einen Teil von Methode 2 verwenden, um den Stapel zu löschen, nachdem Sie zur Master-Detailseite navigiert haben. Seien Sie jedoch vorsichtig - Sie können eine Seite nicht aus dem Stapel entfernen, wenn sie root ist und die aktuell angezeigte Seite Anmeldeseite wird nicht angezeigt. Ich würde diese Option nicht empfehlen als "Modale Ansichten sind oft temporär und auf dem Bildschirm nur lang genug für den Benutzer, um eine Aufgabe abzuschließen."

http://blog.adamkemp.com/2014/09/navigation-in-xamarinforms_2.html

  1. Wenn Sie müssen Sie nicht zurück, um die Folge können Navigationsstapel löschen, wird es auch Back-Taste

    await Navigation.PushAsync(new YourMasterPage()); 
    var pages = Navigation.NavigationStack.ToList(); 
    foreach (var page in pages) 
    { 
        if (page.GetType() != typeof(YourMasterPage)) 
         Navigation.RemovePage(page); 
    } 
    
    entfernen
+0

Es gibt eine interessante Navigationsoption kann auch getan werden. Ihre MasterDetails-Seite kann der Stamm des Navigationsstapels sein. Dann sofort PushModal deine Login- oder Registrierungsseite. Wenn du mit denen fertig bist, die du PopModal hast, lande auf deiner Root MasterPage. Anmeldeseite BTW kann modal auf Registerseite geschoben werden. –

+0

danke Kumpel, hat mir geholfen. –

Verwandte Themen