Navigation stacks
Push registered pages by ViewModel or view and return through the native iOS stack.
INavigator manages the current tab's native navigation stack. Inject it into a ViewModel so navigation does not depend on the page instance:
The destination mappings used here come from page registration.
The registry uses the ViewModel type to find the corresponding page. Passing an existing ViewModel instance preserves the state prepared by the caller.
Push registered destinations
There are three ViewModel forms:
The generic and Type overloads resolve the ViewModel from dependency injection. The object overload uses that instance directly.
Use the PushViewAsync overloads when the destination is naturally view-first:
Create a new page instance for every direct push. Reusing a page that already owns native state can attach one view tree to multiple navigation entries (which will probably crash, whoopsie doopsie :3).
Return through the stack
The native back button and edge-swipe gesture use the same stack. A page's ConfirmLeave callback can veto any attempted pop while it has unsaved state.
Tabs
Each tab has its own navigation stack. SelectTabAsync(title) switches to the title declared by TabsBuilder.Tab. The destination tab keeps its current stack rather than being recreated.
See tabs and iPad for declaring those stacks, iPad-only destinations, and tab accessories.
Tapping the already-selected tab pops to its root when needed, otherwise scrolls the root page's first scrolling view to the top. Set ContentView.TabReselectedCommand to replace that behavior and TabReselectedCommandParameter when the command needs a value.