{"id":58673,"date":"2023-12-25T09:31:18","date_gmt":"2023-12-25T08:31:18","guid":{"rendered":"https:\/\/ar3dp.de\/docs\/programmieren\/xamarin-forms-basis-applikation-app-template\/navigation\/"},"modified":"2023-12-25T09:31:18","modified_gmt":"2023-12-25T08:31:18","slug":"navigation","status":"publish","type":"docs","link":"https:\/\/ar3dp.de\/en\/docs\/programmieren\/xamarin-forms-basis-applikation-app-template\/navigation\/","title":{"rendered":"Navigation"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Das .NET MAUI App Template nutzt unseren <strong>ShellNavigator<\/strong>. Dies ist eine Helper-Klasse, welche alle Funktionen rund um die Shell-Navigation in .NET MAUI vereint.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Verf\u00fcgbare Navigationsarten<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Parameterlose Navigation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Grunds\u00e4tzlich wird unterschieden, ob der Navigation keine, ein oder mehrere Parameter mit der Navigation mitgegeben werden. Eine parameterlose Navigation wechselt einfach von der aktuellen Seite zur der angegeben Seite.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Beispiel einer parameterlosen Navigation<\/h4>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">_ = await ShellNavigator.Instance.GoToAsync(\n    $&quot;\/\/\/{ShellNavigator.Instance.RootPage}&quot;,\n    false,\n    DeviceInfo.Platform == DevicePlatform.Android ? 150 : 50\n    );<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Hier wird die aus dem <strong>LoadingPageViewModel<\/strong> zur definierten Startseite weitergeleitet. Dabei wird der Name der zu navigierenden Seite, sowie angegeben, ob der Vorgang animiert (hier false) und ob eine Wartezeit n\u00f6tig ist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Navigation mit QueryParameters<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Im Gegenzug zu .NET MAUI k\u00f6nnen in Xamarin.Forms keine komplexen Objekte (query parameters) mit \u00fcbergeben werden. Es ist empfohlen, die Objekte in einen <code>String<\/code> zu serialisieren. <\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Beispiel einer Navigation mit Parametern<\/h4>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">_ = await ShellNavigator.Instance.GoToAsync(ShellRoute.NewStockToDepotModalPage, new Dictionary&lt;string, object&gt; {\n    { &quot;depot&quot;, CurrentDepot },\n});<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Beispiel f\u00fchren wir eine Navigation aus um eine neue Aktie zu einem Depot hinzuzuf\u00fcgen. Als Parameter wird hier immer ein W\u00f6rterbuch mit einem Schl\u00fcssel (Name des Parameters) und ein Objekt \u00fcbergeben. In diesem Fall \u00fcbergeben wir das Depot, in welches wir eine neue Aktie einf\u00fcgen m\u00f6chten. In der <code>GoToAsync<\/code> Methode wird der Parameter jedoch serialisiert.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\"> string parameterString = string.Empty;\n int i = 0;\n parameters?.ForEach((p) =&gt;\n {\n     if (p.Value is Guid guid)\n         parameterString += $&quot;{p.Key}={guid}&quot;;\n     else if (p.Value is string plaintext)\n         parameterString += $&quot;{p.Key}={plaintext.Replace(&quot;\\&quot;&quot;, string.Empty)}&quot;;\n     else if (p.Value is IList&lt;Depot&gt; items)\n         \/\/ Use json convert, otherwise line breaks are inside the string.\n         parameterString += $&quot;{p.Key}={JsonConvert.SerializeObject(items.Select(d =&gt; d.Id))}&quot;;\n     else\n         parameterString += $&quot;{p.Key}={JsonConvert.SerializeObject(p.Value)}&quot;;\n     \n     if (i &lt; parameters.Count - 1)\n         parameterString += &quot;&amp;&quot;;\n     i++;\n });\n parameterString = parameterString.Trim();\n await Shell.Current.GoToAsync(state: $&quot;{target}?{parameterString}&quot;, animate: animate);<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Wird eine Liste von Objekten \u00fcbergeben, wie hier im Beispiel die <code>List&lt;Depot><\/code>, dann wird die Liste auf die <code>Guid<\/code> reduziert und serialisiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das Empf\u00e4nger <strong>ViewModel <\/strong>muss jedoch auf diesen Parameter vorbereitet sein. Dies erfolgt mit dem [QueryProperty&#8230;] Attribute, wie unten im Beispiel zu sehen.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">[QueryProperty(nameof(SelectedDepotJson), &quot;depot&quot;)]\n[QueryProperty(nameof(SelectedDepotsJson), &quot;depots&quot;)]\npublic partial class NewStockToDepotModalPageViewModel : AppViewModel\/\/ BaseViewModel\n{\n    #region Parameters\n    \n    [ObservableProperty]\n    string selectedDepotJson;\n    partial void OnSelectedDepotJsonChanged(string value)\n    {\n        SelectedDepot = JsonConvertHelper.ToObject&lt;SelectedDepot&gt;(value);\n    }\n    \n    [ObservableProperty]\n    protected Depot selectedDepot;\n    \n    [ObservableProperty]\n    string selectedDepotsJson;\n    partial void OnSelectedDepotJsonChanged(string value)\n    {\n        if (!string.IsNullOrEmpty(value))\n\t\t{\n    \t\tList&lt;Guid&gt; depotIds = JsonConvertHelper.ToObject&lt;List&lt;Guid&gt;&gt;(value);\n    \t\tSelectedDepots = new(Depots.Where(c =&gt; depotIds.Contains(c.Id)));\n\t\t}\n    }\n    \n    [ObservableProperty]\n    protected List&lt;Depot&gt; selectedDepots;\n    #endregion\n}   <\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Erfolgt eine Navigation mit dem Parameter &#8220;depot&#8221;, so wird dieser beim Aufrufen an das <strong>ViewModel<\/strong> \u00fcbergeben und gesetzt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zur\u00fcck navigieren<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Das Ganze funktioniert auch R\u00fcckw\u00e4rts, sprich wenn der Benutzer eine Seite verl\u00e4sst und dazu den &#8220;Zur\u00fcck&#8221;-Button nutzt. Auch hier kann ein Parameter r\u00fcckw\u00e4rts an den vorherigen Aufrufer \u00fcbergeben werden. Dies ist vor allem dann sinnvoll, wenn in der aktuellen Ansicht zum Beispiel eine neue Aktie erstellt wurde und diese gleich in der vorherigen Ansicht verwendet werden soll.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">_ = await ShellNavigator.Instance.GoToAsync($&quot;..&quot;, new Dictionary&lt;string, object&gt;() { { &quot;stockfound&quot;, SelectedItem } });<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Im obigen Beispiel wird durch die zwei Punkte &#8220;..&#8221; eine R\u00fcckw\u00e4rtsnavigation eingeleitet. Dabei wird zum Beispiel die gefundene Aktie an die Aufrufer-Seite zur\u00fcckgegeben. Auch hier gilt, dass das ViewModel der Aufrufer-Seite auf den Empfang des Parameters &#8220;stockfound&#8221; vorbereitet sein muss.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">await ShellNavigator.Instance.GoBackAsync(new Dictionary&lt;string, object&gt;()\n{\n    { &quot;hcc&quot;, hex },\n});<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Ein anderes Beispiel ist die direkte &#8220;GoBackAsync&#8221; Funktion. Diese unterst\u00fctzt ebenfalls die \u00dcbergabe von Parametern und erf\u00fcllt den gleichen Zweck wie das erste Beispiel mit den zwei Punkten.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ShellRouten und Registrierung neuer Routen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Um die Navigation einfach und \u00fcbersichtlich zu halten, verwendet die App ShellRouten (Enum).<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">public enum ShellRoute\n{\n    LoadingPage,\n\n    \/\/ App\n    SettingsPage,\n    PrivacyPage,\n    AboutPage,\n    VersionDetailPage,\n    ProjectOverviewPage,\n    \/\/...\n}<\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Spiegeln einfach den Namen der verf\u00fcgbaren Seiten wieder. Im Quellcode kann dann einfach \u00fcber den Zugriff auf den <strong>Enum<\/strong> die gew\u00fcnschte Seite aufgerufen werden. Alternativ kann auch ein String \u00fcbergeben werden, welcher \u00fcber die Funktion &#8220;nameof(MyPage)&#8221; die gew\u00fcnschte Zielseite definiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Neue Route registrieren<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Solltet Ihr eine neue Seite zu der App hinzuf\u00fcgen, dann muss diese im ShellNavigator unter der Methode &#8220;RegisterRoutes()&#8221; eingetragen werden, da der Navigator sonst die Route nicht identifizieren kann.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csharp&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;TrpContentRestriction&quot;:{&quot;restriction_type&quot;:&quot;exclude&quot;,&quot;selected_languages&quot;:[],&quot;panel_open&quot;:true},&quot;language&quot;:&quot;C#&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;csharp&quot;}\">public void RegisterRoutes()\n{\n    Routing.RegisterRoute(nameof(AboutPage), typeof(AboutPage));\n    Routing.RegisterRoute(nameof(SettingsPage), typeof(SettingsPage));\n    Routing.RegisterRoute(nameof(PrivacyPage), typeof(PrivacyPage));\n    Routing.RegisterRoute(nameof(VersionDetailPage), typeof(VersionDetailPage));\n    Routing.RegisterRoute(nameof(ProjectOverviewPage), typeof(ProjectOverviewPage));\n    Routing.RegisterRoute(nameof(LoadingPage), typeof(LoadingPage));\n    \/\/...\n}<\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Das .NET MAUI App Template nutzt unseren ShellNavigator. Dies ist eine Helper-Klasse, welche alle Funktionen rund um die Shell-Navigation in .NET MAUI vereint. Verf\u00fcgbare Navigationsarten Parameterlose Navigation Grunds\u00e4tzlich wird unterschieden, ob der Navigation keine, ein oder mehrere Parameter mit der Navigation mitgegeben werden. Eine parameterlose Navigation wechselt einfach von der aktuellen Seite zur der angegeben&#8230;<\/p>","protected":false},"author":1,"featured_media":0,"parent":58608,"menu_order":2,"comment_status":"open","ping_status":"closed","template":"","meta":{"_featured":false,"_is_vendor_doc":"0","footnotes":""},"doc_tag":[],"class_list":["post-58673","docs","type-docs","status-publish","hentry"],"comment_count":0,"_links":{"self":[{"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58673","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs"}],"about":[{"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/types\/docs"}],"author":[{"embeddable":true,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/comments?post=58673"}],"version-history":[{"count":1,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58673\/revisions"}],"predecessor-version":[{"id":58675,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58673\/revisions\/58675"}],"up":[{"embeddable":true,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58608"}],"next":[{"title":"Localization","link":"https:\/\/ar3dp.de\/en\/docs\/programmieren\/xamarin-forms-basis-applikation-app-template\/lokalisierung\/","href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58676"}],"prev":[{"title":"Ersten Schritte","link":"https:\/\/ar3dp.de\/en\/docs\/programmieren\/xamarin-forms-basis-applikation-app-template\/ersten-schritte\/","href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/docs\/58609"}],"wp:attachment":[{"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/media?parent=58673"}],"wp:term":[{"taxonomy":"doc_tag","embeddable":true,"href":"https:\/\/ar3dp.de\/en\/wp-json\/wp\/v2\/doc_tag?post=58673"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}