Passing Navigation Data
Problem
Passing data between pages or view models is a common requirement in modern applications. Without a consistent and reliable method for passing data during navigation, maintaining state and user context can become challenging and error-prone.
Solution
The INavigator
interface provided by Uno.Extensions
allows robust mechanisms to navigate back with results and pass data when navigating.
Passing Data Between ViewModels
In the Chefs app, when applying filters on the SearchPage, we use the NavigateBackWithResultAsync
method from the INavigator
interface.
public async ValueTask ApplySearchFilter(SearchFilter filter) =>
await _navigator.NavigateBackWithResultAsync(this, data: filter);
Applying filters on the Search page
The FilterModel
handles the updating of a SearchFilter
entity. When navigating to FilterModel
from the SearchPage, a SearchFilter
entity can be passed and used for updating an existing SearchFilter
.
The code snippet below shows a Button
that opens the FiltersPage
. The key part is uen:Navigation.Data="{Binding Filter.Value, Mode=TwoWay}"
, which passes the current Filter
value from the SearchModel
to the FilterModel
. Because it's a TwoWay
binding, any changes made in the FiltersPage
are reflected back in the original model after navigation completes.
<Button x:Name="FiltersButton"
uen:Navigation.Data="{Binding Filter.Value, Mode=TwoWay}"
uen:Navigation.Request="!Filter"
Content="Filters"
CornerRadius="20"
Foreground="{ThemeResource PrimaryBrush}"
Style="{StaticResource TextButtonStyle}">
<ut:ControlExtensions.Icon>
<PathIcon Data="{StaticResource Icon_Tune}"
Foreground="{ThemeResource PrimaryBrush}" />
</ut:ControlExtensions.Icon>
</Button>
The updated SearchFilter
with the new filter choices is returned to the SearchPage via NavigateBackWithResultAsync
.
To enable data passing, make sure the navigation routes are properly configured in App.xaml.host.cs
:
In the RegisterRoutes
method, within the view registration block, configure a DataViewMap
like this:
new DataViewMap<SearchPage, SearchModel, SearchFilter>()
Then, in the route registration block, configure the RouteMap
s like this:
new RouteMap("Search", View: views.FindByViewModel<SearchModel>()),
new RouteMap("Filter", View: views.FindByViewModel<FilterModel>())