【WP8】扩展CM的INavigationService方法
CM支持通过ViewModel进行导航,并通过支持参数传递,但是内部只是通过反射的方式构造Uri的参数进行导航,所以只支持简单类型的参数传递,下面对其进行扩展,在页面导航时支持复杂类型的参数传递,并扩展了部分方法,比如,导航后删除上一个页面,清空导航,清空跳转等,详细的看代码
// ************************************************* // // 作者:bomo // 小组:WP开发组 // 创建日期:2014/5/22 23:03:26 // 版本号:V1.00 // 说明: 扩展 CM2.0 的INavigationService // // ************************************************* // // 修改历史: // Date WhoChanges Made // 2014/5/22 23:03:26 bomo Initial creation // // ************************************************* using System; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Navigation; using Caliburn.Micro; namespace XTuOne.Utility.Helpers { /// <summary> /// INavigationService的扩展方法 /// </summary> public static class NavigationExtensions { /// <summary> /// 返回到第一个导航页面 /// </summary> public static void BackToMainView(this INavigationService navigationService) { var count = navigationService.BackStack.Count(); for (int i = 1; i < count; i++) { var entry = navigationService.RemoveBackEntry(); } navigationService.GoBack(); } /// <summary> /// 返回到匹配的导航页面(true:存在且返回成功,false:不存在不操作) /// </summary> public static bool Back2View(this INavigationService navigationService, string pageUri) { if (navigationService.ContainsView(pageUri)) { var list = navigationService.BackStack.ToList(); foreach (var journalEntry in list) { if (!journalEntry.Source.OriginalString.Contains(pageUri)) { var entry = navigationService.RemoveBackEntry(); } else { break; } } navigationService.GoBack(); return true; } return false; } /// <summary> /// 导航后删除上一个导航 /// </summary> public static void NavAndRemoveBack<TViewModel>(this INavigationService navigationService) where TViewModel:class { navigationService.Navigate<TViewModel>(vm => navigationService.RemoveBackEntry()); } /// <summary> /// 根据ViewModel类型跳转到指定页面(清空导航历史) /// </summary> public static void GoToView<T>(this INavigationService navigationService) { navigationService.UriFor<T>().Navigate(); ClearHistory(navigationService); } /// <summary> /// 判断导航历史是否存在ViewModel对应的View /// </summary> public static bool ContainsView<TViewModel>(this INavigationService navigationService) { return navigationService.BackStack.Any(bs => bs.Source.OriginalString.Contains(GetViewUriString<TViewModel>())); } /// <summary> /// 判断导航历史是否存在Page /// </summary> public static bool ContainsView(this INavigationService navigationService, string pageUri) { return navigationService.BackStack.Any(bs=>bs.Source.OriginalString.Contains(pageUri)); } /// <summary> /// 清空导航历史 /// </summary> private static void ClearHistory(INavigationService navigationService) { var count = navigationService.BackStack.Count(); for (int i = 0; i < count; i++) { navigationService.RemoveBackEntry(); } } /// <summary> /// 退出App /// </summary> public static void Exit(this INavigationService navigationService) { if (Environment.OSVersion.Version.Major < 8) { var asmb = Assembly.Load("Microsoft.Xna.Framework.Game, Version=4.0.0.0, Culture=neutral, PublicKeyToken=842cf8be1de50553"); var type = asmb.GetType("Microsoft.Xna.Framework.Game"); var constructorInfo = type.GetConstructor(new Type[] {}); if (constructorInfo != null) { var obj = constructorInfo.Invoke(new object[] {}); type.GetMethod("Exit").Invoke(obj, new object[] {}); } } else { var type = Application.Current.GetType(); type.GetMethod("Terminate").Invoke(Application.Current, new object[] {}); } } /// <summary> /// 通过ViewModel获取View的字符串 /// </summary> public static string GetViewUriString<TViewModel>() { var viewType = ViewLocator.LocateTypeForModelType(typeof (TViewModel), null, null); if (viewType == null) { throw new InvalidOperationException( string.Format("No view was found for {0}. See the log for searched views.", typeof (TViewModel).FullName)); } return ViewLocator.DeterminePackUriFromType(typeof (TViewModel), viewType); } /// <summary> /// 扩展INavigationService,让导航支持复杂对象赋值 /// </summary> public static void Navigate<TViewModel>(this INavigationService navigationService, Action<TViewModel> action) where TViewModel : class { var uri = GetViewUriString<TViewModel>(); NavigatedEventHandler navigationServerOnNavigated = null; navigationServerOnNavigated = (s, e) => { var viewModel = ViewModelLocator.LocateForView(e.Content) as TViewModel; if (viewModel != null) { action(viewModel); } navigationService.Navigated -= navigationServerOnNavigated; }; navigationService.Navigated += navigationServerOnNavigated; navigationService.Navigate(new Uri(uri, UriKind.Relative)); } /// <summary> /// 扩展UriBuilder,让导航支持复杂对象赋值 /// </summary> public static void Navigate<TViewModel>(this UriBuilder<TViewModel> uriBuilder, Action<TViewModel> action) where TViewModel :class { var navigationService = IoC.Get<INavigationService>(); NavigatedEventHandler navigationServerOnNavigated = null; navigationServerOnNavigated= (s, e) => { var viewModel = ViewModelLocator.LocateForView(e.Content) as TViewModel; if (viewModel != null) { action(viewModel); } navigationService.Navigated -= navigationServerOnNavigated; }; navigationService.Navigated += navigationServerOnNavigated; uriBuilder.Navigate(); } } }