MVVMLight 实现指定Frame控件的导航
来源:互联网 发布:Windows安装Python 编辑:程序博客网 时间:2024/06/11 22:33
在UWP开发中,利用汉堡菜单实现导航是常见的方法。汉堡菜单导航一般都需要新建一个Frame控件,并对其进行导航,但是在MvvmLight框架默认的NavigationService中,只能对根Frame进行导航,这就需要我们实现自己的NavigationService了。
MvvmLight源码简析
- GalaSoft.MvvmLight.Views命名空间下的NavigationService继承了同命名空间下的INavigationService接口但是并没有实现。
namespace GalaSoft.MvvmLight.Views{ public class NavigationService : INavigationService { public const string RootPageKey = "-- ROOT --"; public const string UnknownPageKey = "-- UNKNOWN --"; public NavigationService(); public string CurrentPageKey { get; } public void Configure(string key, Type pageType); public void GoBack(); public void NavigateTo(string pageKey); public virtual void NavigateTo(string pageKey, object parameter); }}
- 具体的功能实现是在GalaSoft.MvvmLight.Platform命名空间下的NavigationService中,根据平台的不同有不同的实现。
- 我们要做的就是自己实现INavigationService并自己定义导航的Frame控件
实现自己的NavigationService
很奇怪,官方公布源码的那个网站上没有找到Win10平台的Platform源码,所以我就把Win8.1的NavigationService实现复制下来,经测试能正常用。
在public virtual void NavigateTo(string pageKey, object parameter)方法下,我们可以看到这样一行代码:
var frame = ((Frame)Window.Current.Content);
这个语句就定义了用来导航的Frame控件(不止这个方法中有,另外2个方法中也有类似的语句)。
- 我们把这几个地方的frame变量值设置成自己的Frame控件就可以了。
我的修改方法:
我的Frame控件是放在MainPage中的,主要是为了实现汉堡菜单导航,我想大部分有这种需求的人都是为了实现类似的导航吧。
- 首先在MainPage.xaml.cs里面加入一个MainPage类型的静态Public变量
- 然后再构造函数中给变量赋值为this
还要给自己的Frame控件写一个属性来获取它
public static MainPage MPage; // 1.public Frame MyFrame // 3.{ get { return ContentFrame; //ContentFrame是xaml中定义的Frame控件的名字 }}public MainPage(){ InitializeComponent(); SystemNavigationManager.GetForCurrentView().BackRequested += SystemNavigationManagerBackRequested; Loaded += (s, e) => { Vm.RunClock(); }; MPage = this; // 2.}
然后就可以在自己的NavigationService里面使用自己的Frame了。
//var frame = ((Frame)Window.Current.Content); // 之前的语句var frame = MainPage.MPage.MyFrame; // 自己写的新语句
这样我们就把NavigationService的导航Frame设置成了MainPage里面的ContentFrame控件。
- 不过我这个方法还不是最优的,因为这样写就把MainPage和NavigationService直接联系起来了,增加了耦合性。我看到WPF中可以通过下面这个方法来获取指定名字的Frame控件,不过在UWP里面没有这个方法。
var frame = GetDescendantFromName(Application.Current.MainWindow, "MainFrame") as Frame;
如果谁有更好的办法的话麻烦在评论里面告诉我,万分感谢。
效果图
MyNavigationService代码
using GalaSoft.MvvmLight.Views; using Mvvm_HutHelper.View; using System; using System.Collections.Generic; using System.Linq; namespace Mvvm_HutHelper.Model { class MyNavigationService : INavigationService { /// <summary> /// The key that is returned by the <see cref="CurrentPageKey"/> property /// when the current Page is the root page. /// </summary> public const string RootPageKey = "-- ROOT --"; /// <summary> /// The key that is returned by the <see cref="CurrentPageKey"/> property /// when the current Page is not found. /// This can be the case when the navigation wasn't managed by this NavigationService, /// for example when it is directly triggered in the code behind, and the /// NavigationService was not configured for this page type. /// </summary> public const string UnknownPageKey = "-- UNKNOWN --"; private readonly Dictionary<string, Type> _pagesByKey = new Dictionary<string, Type>(); /// <summary> /// The key corresponding to the currently displayed page. /// </summary> public string CurrentPageKey { get { lock (_pagesByKey) { //var frame = ((Frame)Window.Current.Content); var frame = MainPage.MPage.MyFrame; if (frame.BackStackDepth == 0) { return RootPageKey; } if (frame.Content == null) { return UnknownPageKey; } var currentType = frame.Content.GetType(); if (_pagesByKey.All(p => p.Value != currentType)) { return UnknownPageKey; } var item = _pagesByKey.FirstOrDefault( i => i.Value == currentType); return item.Key; } } } /// <summary> /// If possible, discards the current page and displays the previous page /// on the navigation stack. /// </summary> public void GoBack() { //var frame = ((Frame)Window.Current.Content); var frame = MainPage.MPage.MyFrame; if (frame.CanGoBack) { frame.GoBack(); } } /// <summary> /// Displays a new page corresponding to the given key. /// Make sure to call the <see cref="Configure"/> /// method first. /// </summary> /// <param name="pageKey">The key corresponding to the page /// that should be displayed.</param> /// <exception cref="ArgumentException">When this method is called for /// a key that has not been configured earlier.</exception> public void NavigateTo(string pageKey) { NavigateTo(pageKey, null); } /// <summary> /// Displays a new page corresponding to the given key, /// and passes a parameter to the new page. /// Make sure to call the <see cref="Configure"/> /// method first. /// </summary> /// <param name="pageKey">The key corresponding to the page /// that should be displayed.</param> /// <param name="parameter">The parameter that should be passed /// to the new page.</param> /// <exception cref="ArgumentException">When this method is called for /// a key that has not been configured earlier.</exception> public virtual void NavigateTo(string pageKey, object parameter) { lock (_pagesByKey) { if (!_pagesByKey.ContainsKey(pageKey)) { throw new ArgumentException( string.Format( "No such page: {0}. Did you forget to call NavigationService.Configure?", pageKey), "pageKey"); } //var frame = ((Frame)Window.Current.Content); // 这句设置导航时用到的Frame控件为根Frame var frame = MainPage.MPage.MyFrame; frame.Navigate(_pagesByKey[pageKey], parameter); } } /// <summary> /// Adds a key/page pair to the navigation service. /// </summary> /// <param name="key">The key that will be used later /// in the <see cref="NavigateTo(string)"/> or <see cref="NavigateTo(string, object)"/> methods.</param> /// <param name="pageType">The type of the page corresponding to the key.</param> public void Configure(string key, Type pageType) { lock (_pagesByKey) { if (_pagesByKey.ContainsKey(key)) { throw new ArgumentException("This key is already used: " + key); } if (_pagesByKey.Any(p => p.Value == pageType)) { throw new ArgumentException( "This type is already configured with key " + _pagesByKey.First(p => p.Value == pageType).Key); } _pagesByKey.Add( key, pageType); } } } }
参考资料
MVVM Light 5.0: How to use the Navigation service
MvvmLight SourceCode
阅读全文
1 0
- MVVMLight 实现指定Frame控件的导航
- 利用frame实现简单的导航功能
- frame简单实现导航
- frame实现菜单导航
- 如何实现指定frame的单独前进、后退?
- 使用mvvmlight for win8 让GridViewItem项 实现动态命令导航
- 使用mvvmlight for win8 让GridViewItem项 实现动态命令导航
- 打印控件的 frame
- html里frame导航框架实现方法
- MVVMLight的使用方法
- MVVMLight的Messenger
- MVVMLight的使用方法
- MVVMLight
- Window,Document,Frame的理解,帮助理解左侧导航栏的实现原理
- 改变控件label的Frame
- 控件旋转frame的计算
- frame动画的实现
- frame动画的实现
- ubuntu: 终端全屏快捷键
- svn分支合并到主干
- Android 软键盘 解析
- python异常的抛出机制
- mac 系统清除内存
- MVVMLight 实现指定Frame控件的导航
- 判断特定Activity是否在前台显示
- C++命名规则
- mysql 存储过程
- 筑讯材料·土|地漏小百科
- 通用接口测试用例设计
- struts2耦合和非耦合设置值和获取的方式
- POJ 1724 ROADS
- PythonWeb开发Django框架学习(十二)基础总结