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.
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.
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. –
danke Kumpel, hat mir geholfen. –