项目介绍
MPowerKit 是.NET MAUI 的导航框架。
项目支持常规/模式导航,打开/关闭窗口,多窗口、区域导航和弹出窗口。
项目灵感来自于Prism项目,Prism对MAUI的支持不是很友好。因此作者开发了针对MAUI的导航框架。提供了与Prism相同的MAUI应用程序导航原则,但实现方式完全不同。性能也略有提高。带来了正确的方式处理所有平台相同行为的系统返回按钮功能。
项目地址
https://github.com/MPowerKit/Navigation
相关接口介绍
MPowerKit.Navigation.Core 核心库的相关接口
IInitializeAware只有一个void Initialize(INavigationParameters parameters);方法,这个方法在页面和它的视图模型创建后立即执行,并且没有附加到可视化树。在该页的生存期内仅执行一次。如果你想让页面或者视图模型知道这个事件,必须实现这个接口。IDestructible只实现void Desctroy();,从可视化树中分离出来并且在GC之后立即实行。按倒序连续的对导航堆栈中的每隔页面执行。在页面生存期内仅执行一次。如果你想让页面或者视图模型知道这个事件,必须实现这个接口。INavigationAware此接口实现了两个方法void OnNavigatedFrom(INavigationParameters parameters);返回上层页面时调用。void OnNavigatedTo(INavigationParameters parameters);进入当前页面时调用。
IPageLifecycleAware该接口绑定到Page类的生命周期事件。有两个接口方法:void OnAppearing();当页面出现时执行。void OnDisappearing();当页面消失时执行。
IWindowLifecycleAware与Window类的生命周期事件绑定,有两个方法:void OnResume();和void OnSleep();ISystemBackButtonClickAware如果想要完全控制导航功能,需要在Page或者ViewModel中实现这个接口。只有一个方法:bool OnSystemBackButtonClick();。 此方法在单击系统返回按钮时执行,可在MAUI支持的所有平台上有效。返回值表示是否处理此事件。如果处理了,那么向后导航应该有开发人员处理。如果没有,在向后导航将由MAUI本身处理。IActiveTabAware这个接口只有一个方法:bool IsOnActiveTab { get; set; }。用于表示页面是否在活动状态IFlyoutPageFlyoutPresentedAware
使用方法
使用时在项目中引用对应的nuget包即可。可搜索MPowerKit,找到对应相关库即可。
MPowerKit.Navigation导航功能MPowerKit.Regions区域功能MPowerKit.Navigation.Popups弹出功能
根据自己的需要添加相关库即可。
MPowerKit.Navigation
此库提供了必要的基础功能,并以完全MVVM的方式构建了丰富的应用程序,提供了不同页面之间的导航。
需要在MauiProgram中添加如下代码:
builder.UseMauiApp<App>().UseMPowerKitNavigation(mpowerBuilder =>{mpowerBuilder.ConfigureServices(s =>{s.RegisterForNavigation<MainPage>();}).OnAppStart("NavigationPage/MainPage");});
启动应用程序时,以MainPage作为根页面启动。如果想要注册服务你可以在ConfigureServices中添加代码。在此库中已添加了必要的一下服务。如果你想进行扩展可以自己更改相关功能:
- MPowerKitWindow 注册为瞬态服务IMPowerKitWindow,并提供处理系统返回按钮和窗口生命周期的能力,如果需要更改
MPowerKitWindow的实现或者改变西的后退按钮点击行为,可以扩展这个类并注册新的实现。
mpowerBuilder.ConfigureServices(s =>
{s.AddTransient<IMPowerKitWindow, NewWindowThatExtendsMPowerKitWindow>();
});
- NavigationService 作为作用域服务注册,应用程序导航,如果需要覆盖它的一些基本实现,可以使用你的实现并使用如下注册:
mpowerBuilder.ConfigureServices(s =>
{s.AddScoped<INavigationService, YourNavigationService>();
});
注册页面
方法一:
mpowerBuilder.ConfigureServices(s =>
{s.RegisterForNavigation<MainPage>(); //解析为`nameof`,没有指定视图模型,这意味着将BindingContext设置为new object
})
方法二:
mpowerBuilder.ConfigureServices(s =>
{s.RegisterForNavigation<MainPage, MainPageViewModel>();//解析为`nameof`,并指定view model为`MainPageViewModel`
})
方法三:
mpowerBuilder.ConfigureServices(s =>
{s.RegisterForNavigation<MainPage, MainPageViewModel>("TheAssociationNameForYourPage");//解析为关联名称,这是首选方式,并指定view model为`MainPageViewModel`
})
已注册页面
NavigationPageTabNavigationPageTabbedPageFlyoutPage
注册自己的行为
如果需要使用已经附加的行为来解析页面,可以实现如下代码:
mpowerBuilder.ConfigureServices(s =>
{// Register behaviorss.RegisterBehavior<Page, SomeUsefulBehaviorYouWantToAttachToEachPageInYourApp>();s.RegisterBehavior<SecondPage, SomeUsefulBehaviorYouWantToAttachOnlyToSecondPage>();
})
已存在的行为
PageLifecycleAwareBehavior负责处理页面的OnAppearing() 和OnDisappearing()事件,在应用中所有页面中已注册。TabbedPageActiveTabAwareBehavior负责处理TabbedPage的CurrentPageChanged事件。FlyoutPageFlyoutPresentedAwareBehavior负责处理FlyoutPage的IsPresentedChanged事件
配置应用启动
大多数情况下,使用下面的设置足以在所需要页面启动应用程序。
mpowerBuilder.OnAppStart("NavigationPage/YourPage");
如果需要一些初始化的工作,可使用如下方法:
OnInitialized()
//方法一(无参):
mpowerBuilder.OnInitialized(() =>
{//your initializations
});
//方法二(带参)
mpowerBuilder.OnInitialized(serviceProvider =>
{//your initializations
});
OnAppStart当应用程序准备好导航到第一页面时执行,这是必须的,如果没有它,应用程序在开始就会崩溃。
mpowerBuilder.OnAppStart("NavigationPage/YourPage");
如果想在导航前执行一些异步方法,可用如下代码,提供一个登录功能。
mpowerBuilder.OnAppStart(async (serviceProvider, navigationService) =>
{if (await IsUserLoggedIn()){await navigationService.NavigateAsync("NaviationPage/MainPage");}else await navigationService.NavigateAsync("LoginPage");
});
使用
要在应用中使用导航,你需要将INavigationService注入到你的页面或者视图的构造函数中,然后就可以导航到想要的页面
INavigationService _navigationService;await _navigationService.NavigateAsync("YourPageAssociationName", optionalNavigationParameters, optionalIsModal, optionalIsAnimated);
每个页面或者VM都有自己的INavigationService实例,它被注册为作用域服务。
导航到页面:
ValueTask<NavigationResult> NavigateAsync(string uri, INavigationParameters? navigationParameters = null, bool modal = false, bool animated = true);
返回
要会到上一页或者根页,可以冲任何页面或者VM中执行此操作。
ValueTask<NavigationResult> GoBackAsync(INavigationParameters? parameters = null, bool modal = false, bool animated = true);
ValueTask<NavigationResult> GoBackToRootAsync(INavigationParameters? parameters = null, bool animated = true);
打开新窗口或者关闭窗口
ValueTask<NavigationResult> OpenNewWindowAsync(string uri, INavigationParameters? parameters = null);
NavigationResult CloseWindow(Guid? windowId = null);
MPowerKit.Navigation.Popups
弹窗功能这个库基于 MPowerKit.Navigation和MPowerKit.Popups
使用UsePopupNavigation()进行引用,如下所示:
builder.UseMauiApp<App>().UseMPowerKitNavigation(mpowerBuilder =>{mpowerBuilder.ConfigureServices(s =>{s.RegisterForNavigation<MainPage>();s.RegisterForNavigation<TestPopupPage>();}).UsePopupNavigation().OnAppStart("NavigationPage/MainPage");});
注册Popup页面可参考注册页面
每一个弹出页面,必须集成库MPowerKit.Popups中的PopupPage。
可通过在构造函数中注册接口IPopupDialogAware实现弹窗功能,可进行参数传递和关闭功能。如下示例所示:
public class TestPopupViewModel : IPopupDialogAware
{public Action<(Confirmation Confirmation, bool Animated)> RequestClose { get; set; }protected virtual async Task Cancel(object obj = null){var nparams = new NavigationParameters{{ NavigationConstants.CloseParameter, obj }};RequestClose?.Invoke((new Confirmation(false, nparams), true));}protected virtual async Task Confirm(object obj = null){var nparams = new NavigationParameters{{ NavigationConstants.CloseParameter, obj }};RequestClose?.Invoke((new Confirmation(true, nparams), true));}
}
MPowerKit.Navigation.Regions
与Prism的导航功能相似,但是实现方式不同。
添加UseMPowerKitRegions() 到MauiProgram.cs文件中:
builder.UseMauiApp<App>().UseMPowerKitRegions();
builder.UseMauiApp<App>().UseMPowerKitNavigation(mpowerBuilder =>{mpowerBuilder.ConfigureServices(s =>{s.RegisterForNavigation<MainPage>();s.RegisterForNavigation<RegionView1>();}).OnAppStart("NavigationPage/MainPage");}).UseMPowerKitRegions();
如果你将区域与MPowerKit.Navigation结合使用,你可以指定是否想要你的区域视图获得父页面的事件,如导航、销毁、生命周期等,只需要将UsePageEventsInRegions()到你代码中。
builder.UseMauiApp<App>().UseMPowerKitNavigation(mpowerBuilder =>{mpowerBuilder.ConfigureServices(s =>{s.RegisterForNavigation<MainPage>();s.RegisterForNavigation<RegionView1>();}).UsePageEventsInRegions()//此行代码.OnAppStart("NavigationPage/MainPage");}).UseMPowerKitRegions();
注册region页面可参考注册页面
使用
每个区域应该有一个父容器,类型为ContentView。
添加命名空间:
xmlns:regions="clr-namespace:MPowerKit.Regions;assembly=MPowerKit.Regions"
//添加一个简单的区域
<ContentView regions:RegionManager.RegionName="YourVeryMeaningfulRegionName" />//与Prism不同,它可以有一个动态名称,如下所示
<ContentView regions:RegionManager.RegionName="{Binding DynamicString}" />
注意:区域名称必须为唯一的,否则应用会崩溃。
IRegionManager将此接口注入到页面或者VM的构造函数中,使用方法
IRegionManager _regionManager;_regionManger.NavigateTo("YourRegionName", "RegionViewAssociationName", optionalNavigationParametersObject);
此文已在公众号:MAUI与Avalonia开启原创,欢迎关注与转载。