MVVMLight 实现指定Frame控件的导航
在UWP開發中,利用漢堡菜單實現導航是常見的方法。漢堡菜單導航一般都需要新建一個Frame控件,并對其進行導航,但是在MvvmLight框架默認的NavigationService中,只能對根Frame進行導航,這就需要我們實現自己的NavigationService了。
MvvmLight源碼簡析
- GalaSoft.MvvmLight.Views命名空間下的NavigationService繼承了同命名空間下的INavigationService接口但是并沒有實現。
- 具體的功能實現是在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控件。
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控件為根Framevar 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
posted on 2018-06-06 14:33 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/lonelyxmas/p/9144982.html
總結
以上是生活随笔為你收集整理的MVVMLight 实现指定Frame控件的导航的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poj3009深度优先搜索挑战程序设计竞
- 下一篇: KVM虚拟机搭建增量镜像(一个基本镜像拷