Anleitung: Navigation im Model oder ViewModel
Nun wollen wir uns einmal anschauen, wie wir passend zur Uno Extensions Navigation unsere Verbindung zwischen der View und dem ViewModel aufbauen müssen.
Hierfür wollen wir uns natürlich ersteinmal die Frage stellen: Navigation nur im Xaml - Geht das eigentlich?
Ja und Nein.
Also, dann lass uns das doch mal genauer betrachten. Was bedeutet das denn nun?
Ja:
Tatsächlich brauchst du grundsätzlich weder Codebehind noch Code im ViewModel / Model für die Navigation, wenn du die
Attached Propertiesin dem Xaml deiner Seite nutzt.Wie das geht, erfährst du bei Interesse direkt hier:
Anleitung: Definieren des UI mit NavigationView für ExtensionsNavigation
In diesem Fall wären es dann nur zum beispiel die anzuzeigende Eigenschaft, wie die
string-PropertyTitle, die du entsprechend in deinerPage, also deinerViewzumViewModelbzw.Modelbindest und schon bist du fertig damit!Tip
Mit der
Attached Propertyuen:Navigation.Requestbzw.uen:Navigation.Datakannst du übrigens auch Daten an die Navigation übergeben, wie in der Uno Dokumentation gut anhand vonWidget-Elementen erklärt wird hierfür benötigst du dann bspw. aber wiederDataViewMap-Definitionen in der Routen Registrierung.Nein:
- Du musst weiterhin die Routen, die du Navigieren möchtest in der
App.xaml.csKlasse in derRegisterRoutesMethode registrieren, damit derINavigatorauch weiß, was zusammen gehört und von wo du mit welchen "Qualifizierern" welche Routen erlauben möchtest zu navigieren. - Wenn du in deinem Model bzw. ViewModel eine Navigation auslösen möchtest, dann brauchst du den
INavigatordort natürlich, um die Navigation zu starten.
- Du musst weiterhin die Routen, die du Navigieren möchtest in der
Vorraussetzungen schaffen
Gut, also lass uns doch mal davon ausgehen, dass wir genannten zweiten Fall haben und folgendes Tun wollen:
Unser Anwender soll mit einem Klick auf einen
Buttoneine Funktion in unseremViewModelbzw.Modelauslösen könnenDiese Funktion soll ihn zur
SecondPagenavigieren, die wir in der Uno App Vorlage inkludiert hatten, aber es könnte auch jede andere Seite sein, die du selbst erstellt und registriert hast.Angenommen das hier ist unsere
App.xaml.csmit derRegisterRoutesMethode:{ views.Register( new ViewMap(ViewModel: typeof(ShellModel)), new ViewMap<MainPage, MainModel>(), new DataViewMap<SecondPage, SecondViewModel, Entity>() ); routes.Register( new RouteMap("", View: views.FindByViewModel<ShellModel>(), Nested: [ new RouteMap("Main", View: views.FindByViewModel<MainModel>(), IsDefault:true), new RouteMap("Second", View: views.FindByViewModel<SecondModel>()) ] ) ); }
Aber wie muss dafür unser ViewModel bzw. Model aussehen, damit wir das umsetzen können?
Hierfür brauchen wir erstmal folgendes Schritte:
Binden der View UI Steuerelemente an Eigenschaften im ViewModel bzw. Model
Nun haben wir zuvor den Title der NavigationView manuell festgelegt, aber wie sieht es mit anderen Eigenschaften aus, die wir in der View binden wollen? Und du hast in der Template App vielleicht auch den Name gesehen, der in der Dashboard(View)Model definiert ist.
Wenn du nicht vom Template startest, füge diese Eigenschaft hinzu, um sie in der View zu binden.
public string? Name { get; set; }
public partial class DashboardViewModel : ObservableObject
{
private readonly INavigator _navigator;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(NavigateSecondAsyncCommand))]
private string? name;
public DashboardViewModel(INavigator navigator)
{
_navigator = navigator;
NavigateSecondAsyncCommand = new AsyncRelayCommand(NavigateSecondAsync);
}
public IAsyncRelayCommand NavigateSecondAsyncCommand { get; }
[RelayCommand(CanExecute = nameof(CanExecuteNavigateSecondAsync))]
private async Task NavigateSecondAsync()
{
await _navigator.NavigateViewModelAsync<SecondViewModel>(this, data: new Entity(Name!));
}
private bool CanExecuteNavigateSecondAsync()
{
return !string.IsNullOrWhiteSpace(Name);
}
}
Mit diesem Code ist es dir möglich, die Name Eigenschaft in der View zu binden und den NavigateSecondAsyncCommand zu verwenden, um zur SecondViewModel zu navigieren.
Hierbei kannst du einen Button oder ein anderes Steuerelement in der View verwenden, um die Navigation auszulösen, aber indem du die IsEnabled Eigenschaft des Steuerelements an den CanExecute Status des Befehls bindest, kannst du die Navigation nur dann ausführen, wenn der Name nicht leer ist.