public
interface
INavigationAware
{
bool
IsNavigationTarget(NavigationContext navigationContext);
void
OnNavigatedTo(NavigationContext navigationContext);
void
OnNavigatedFrom(NavigationContext navigationContext);
}
当从本页面转到其它页面的时候,会调用OnNavigatedFrom方法,navigationContext会包含目标页面的URI。
当从其它页面导航至本页面的时候,首先会调用IsNavigationTarget,IsNavigationTarget返回一个bool值,简单地说这个方法的作用就是告诉Prism,是重复使用这个视图的实例还是再创建一个。然后调用OnNavigatedTo方法。在导航到本页面的时候,就可以从navigationContext中取出传递过来的参数。
在prism中要实现页面导入时传入参数中比如MyView?param1=abc¶m2=123,如何获得这些参数呢?这就要实现INavigationAware接口。
上面那个视图View叫MyView,假设它的ViewModel叫MyViewModel,那个这个ViewModel必须实现INavigationAware接口。
INavigationAware接口源码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public interface INavigationAware { bool IsNavigationTarget(NavigationContext navigationContext); void OnNavigatedTo(NavigationContext navigationContext); void OnNavigatedFrom(NavigationContext navigationContext); }
这三个方法都很重要:
- IsNavigationTarget方法:当前的视图模型是否可以处理请求的导航行为,通常用来指定当前的视图/模型是否可以重用。例如,一个显示客户明细的视图可以显示客户a,客户b....等的信息,他们重用同一个视图。
- OnNavigatedTo方法:当前的页面被导航到以后发生,这个函数可以用来处理URI的参数。
- OnNavigatedFrom方法:当前的页面导航到其他页面的时候发生。
这里给出一个实现了INavigationAware接口的ViewModel例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[Export("MyViewModel ", typeof(MyViewModel ))] [PartCreationPolicy(CreationPolicy.NonShared)] public class MyViewModel : INavigationAware { private IRegionNavigationJournal navigationJournal; bool INavigationAware.IsNavigationTarget(NavigationContext navigationContext) { return true; } void INavigationAware.OnNavigatedFrom(NavigationContext navigationContext) { // Intentionally not implemented. } void INavigationAware.OnNavigatedTo(NavigationContext navigationContext) { var pram1 = navigationContext.Parameters["param1"]; UpdateDataAsync(pram1 ); this.navigationJournal = navigationContext.NavigationService.Journal; } }
在上面的例子中,OnNavigatedTo方法获取了URI的参数,当参数发生变化自动重新获取数据刷新ViewModel。这个场景可以用在:例如,一个显示客户明细的视图可以显示客户a,客户b....等的信息,他们重用同一个视图。当我们navigate导航到URI:MyView?param1=abc¶m2=123的时候,导航到同一个视图但客户ID变化,放在URI的参数中传递,OnNavigatedTo方法获取了URI的参数,重用当前视图,同时刷新数据。整个过程很清晰。
IConfirmNavigationRequest接口
有些时候当我们导航到其他页面的时候,需要弹出一个框提示用户“是否放弃修改?保存、放弃、取消”,这就需要实现IConfirmNavigationRequest接口。还是上面那个例子,那个ViewModel还要实现IConfirmNavigationRequest接口。这样这个ViewModel既实现了INavigationAware接口又实现了IConfirmNavigationRequest接口,触发的顺序如下:
- 导航发生的时候,如果目标也实现了IConfirmNavigationRequest接口,那么先自动调用ConfirmNavigationRequest.
- ViewModel触发interaction来打开一个“是否放弃修改?保存、放弃、取消” 确认的UI。
- 当用户选择了"保存、放弃、取消”以后interaction的callback自动触发
- 根据用户的选择决定是否继续导航
来一个例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
ViewModel实现了IConfirmNavigationRequest接口 public class ComposeEmailViewModel : NotificationObject, IConfirmNavigationRequest { private readonly InteractionRequest<Confirmation> confirmExitInteractionRequest; public ComposeEmailViewModel(IEmailService emailService) { this.confirmExitInteractionRequest = new InteractionRequest<Confirmation>(); } public IInteractionRequest ConfirmExitInteractionRequest { get { return this.confirmExitInteractionRequest; } } } XAML定义Interaction <UserControl.Resources> <DataTemplate x:Name="ConfirmExitDialogTemplate"> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}"/> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot" Background="White"> <ei:Interaction.Triggers> <prism:InteractionRequestTrigger SourceObject="{Binding ConfirmExitInteractionRequest}"> <prism:PopupChildWindowAction ContentTemplate="{StaticResource ConfirmExitDialogTemplate}"/> </prism:InteractionRequestTrigger> </ei:Interaction.Triggers> ... 用户确认 void IConfirmNavigationRequest.ConfirmNavigationRequest( NavigationContext navigationContext, Action<bool> continuationCallback) { this.confirmExitInteractionRequest.Raise( new Confirmation {Content = "...", Title = "..."}, c => {continuationCallback(c.Confirmed);}); }