Navigation via Code Behind
Problem
Navigation logic can often become complex when it has to handle different states and pass data. These situations can lead to decreased readability and reusability.
Solution
Uno Extensions Navigation lets you easily invoke navigation with INavigator
through commands defined in the view model, enabling more flexibility and more maintainable code. It is also possible to navigate between pages.
1. NavigateViewModelAsync
This method navigates to a route that matches the specified view model type. Let's say we want to navigate to the search page and display popular recipes. To do so, we can use NavigateViewModelAsync
to navigate to the SearchModel and we can add a SearchFilter
as data to specify that the recipes should be organized by popularity.
public async ValueTask SearchPopular() =>
await _navigator.NavigateViewModelAsync<SearchModel>(this, data: new SearchFilter(FilterGroup: FilterGroup.Popular));
2. NavigateDataAsync
This method navigates to a route that is registered for the specified data type. In the root App.xaml.host.cs, since we defined that the GenericDialogModel
is registered to a DialogInfo
through the DataMap
, it will choose the "Dialog" route.
public static Task<NavigationResponse?> ShowDialog(this INavigator navigator, object sender, DialogInfo dialogInfo, CancellationToken ct)
{
return navigator.NavigateDataAsync(sender, new DialogInfo(dialogInfo.Title, dialogInfo.Content), cancellation: ct);
}
private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes)
{
views.Register(
/* other routes */,
new ViewMap<GenericDialog, GenericDialogModel>(Data: new DataMap<DialogInfo>())
);
routes.Register(
/* other routes */,
new RouteMap("Dialog", View: views.FindByView<GenericDialog>())
);
}
3. NavigateBackAsync
This method navigates back to the previous frame on the back-stack.
private async Task NavigateBack()
{
await _navigator.NavigateBackAsync(this);
}
4. NavigateBackWithResultAsync
This method navigates back to the previous frame on the back-stack with data. Let's say the previous page the user was on was the search page and it was displaying recipes with a certain filter. What if the user navigates to the filter page, changes the search filters, and once submitted is navigated back to the search page? We could use NavigateViewModelAsync
but that would mean remaking the SearchModel
. That's why we should use NavigateBackWithResultAsync
and pass the new filter as data. We can define a DataViewMap
to register that the route is expecting a SearchFilter as a parameter when being navigated to.
private static void RegisterRoutes(IViewRegistry views, IRouteRegistry routes)
{
views.Register(
/* other routes */,
new DataViewMap<SearchPage, SearchModel, SearchFilter>()
);
}
public async ValueTask ApplySearchFilter(SearchFilter filter) =>
await _navigator.NavigateBackWithResultAsync(this, data: filter);
5. NavigateRouteAsync
This method navigates to a registered route, if it exists, without having to specify a view model.
public async ValueTask LiveCooking(IImmutableList<Step> steps, CancellationToken ct)
{
await _navigator.NavigateRouteAsync(this, "LiveCooking", data: new LiveCookingParameter(Recipe, steps), cancellation: ct);
}