【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();
        }
    }
}

 

posted @ 2014-07-13 10:12  bomo  阅读(1064)  评论(0编辑  收藏  举报