导航到现有视图
通常在导航期间重用、更新或激活应用程序中的视图比用新视图替换更适合。这通常会发生在您导航到相同类型的视图但需要向用户显示不同的信息或状态时,或者当适当的视图已经在UI中可用但需要被激活(即选择或设置为最顶层)。
对于第一个场景的例子,可以假想您的应用程序允许用户使用EditCustomer视图编辑客户记录,并且用户当前正在使用该视图编辑客户ID 123。如果客户决定编辑客户ID 456的客户记录,用户只需导航到EditCustomer视图并输入新的客户ID。然后EditCustomer视图可以检索新客户的数据并相应地更新其UI。
第二种情况的场景是应用程序允许用户一次编辑多个客户记录。在这种情况下应用程序在选项卡控件中显示多个EditCustomer视图实例——例如,一个用于客户ID 123,另一个用于客户ID 456。当用户导航到EditCustomer视图并输入客户时ID 456,对应的view会被激活(即它对应的tab会被选中)。如果用户导航到EditCustomer视图并输入客户ID 789,将创建一个新实例并显示在选项卡控件中。
导航到现有视图的能力很有用,原因有很多。更新已有的视图通常比用相同类型的新实例替换它更高效。同样激活现有视图而不是创建重复视图可提供更一致的用户体验。 此外无需大量自定义代码即可无缝处理这些情况的能力意味着应用程序更易于开发和维护。
Prism通过INavigationAware接口上的IsNavigationTarget方法支持前面描述的两种场景。其会在导航区域中与目标视图类型相同的所有视图期间调用此方法。在前面的示例中,视图的目标类型是EditCustomer视图,因此IsNavigationTarget方法会在该区域中当前所有现有的EditCustomer视图实例上调用。其中Prism将从视图URI确定目标类型,它会假定EditCustomer是目标类型的短类型名称。
注意: 为了让Prism确定目标视图的类型,导航URI中的视图名称应与实际目标类型的短类型名称相同。例如如果您的视图是由MyApp.Views.EmployeeDetailsView类实现的,则导航URI中指定的视图名称应为EmployeeDetailsView。这是Prism提供的默认行为。您可以通过实现自定义内容加载器类来自定义此行为:通过实现IRegionNavigationContentLoader接口或通过从RegionNavigationContentLoader类派生来实现此行为。
IsNavigationTarget方法的实现可以使用NavigationContext参数来确定它是否可以处理导航请求。NavigationContext对象提供了对导航URI和导航参数的访问。在前面的例子中这个方法会在EditCustomer视图模型中实现,它将当前客户ID与导航请求中指定的ID进行比较,如果匹配就返回true。
public class EmployeeDetailsViewModel : BindableBase, INavigationAware
{
public bool IsNavigationTarget(NavigationContext navigationContext)
{
string id = navigationContext.Parameters["ID"];
return _currentCustomer.Id.Equals(id);
}
public void OnNavigatedTo(NavigationContext navigationContext) { }
public void OnNavigatedFrom(NavigationContext navigationContext) { }
}
如果IsNavigationTarget方法始终返回true,则无论导航参数是什么,该视图实例将始终被重新使用。这允许您确保在特定区域中仅显示一个特定类型的视图。