Prism框架(3)—导航的使用

使用场景

在普遍的业务场景当中, 必不可少的是页面切换, 而Prism就可以使用Navigation功能来进行页面导航, 在不同的场景当中会有各种用法, 例如在切换页面验证、传递参数、返回上一页、返回下一页等功能。

 导航的基本条件

  • 1.注册显示区域
  • 2.注册导航页面

1.注册导航

  • 注册视图类型或添加别名, 如果为指定别名,名称默认为当中类型的名称
public class ModuleAModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //添加别名 "CustomName"
            containerRegistry.RegisterForNavigation<ViewA>("CustomName");
            //默认名称 "ViewB"
            containerRegistry.RegisterForNavigation<ViewB>();
        }
    }
  • 注册时,指定ViewModel或添加别名。
 public class ModuleAModule : IModule
    {
        public void OnInitialized(IContainerProvider containerProvider)
        {

        }

        public void RegisterTypes(IContainerRegistry containerRegistry)
        {
            //指定ViewModel
            containerRegistry.RegisterForNavigation<ViewA, ViewAViewModel>();
            //指定ViewModel并且添加别名
            containerRegistry.RegisterForNavigation<ViewB, ViewBViewModel>("CustomName");
        }
    }

2.使用导航

正如前面的章节所讲到, Region的注册以及管理、导航等, 我们可以使用IRegionManager接口,所以,我们现在便可以使用该接口实现导航功能, 如下所示:

IRegionManager regionManager = …;
regionManager.RequestNavigate("RegionName", "ViewName");

可以注意点, 我们调用了IRegionManager接口的RequestNavigate方法, 并且传递了两个参数:

  • RegionName: 该参数为注册的区域名称
  • ViewName: 该参数实际为我们上面注册过的导航页, 字符串类型, 对应的是我们注册页面的nameof

3.带参数导航

正如,我们想要在导航页前, 传递一些参数, 则可以使用NavigationParameters, 如下所示:

var param = new NavigationParameters();
param.Add("Parameter", param);
_regionManger.RequestNavigate("RegionName", "ViewName", param);

//类似URL地址传递参数
_regionManger.RequestNavigate("RegionName", "ViewName?id=1&Name=xiaoming");

疑问?

当我们使用导航为指定区域注册视图时, 我们怎么控制打开的过程? 所以, 下面我们将讲解一下
INavigationAware接口。

INavigationAware

该接口包含3个方法, 每个方法中都包含当前导航的上下文, 如下所示:

        public void OnNavigatedTo(NavigationContext navigationContext)
        {

        }

        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        public void OnNavigatedFrom(NavigationContext navigationContext)
        {

        }
  • OnNavigatedTo: 导航完成前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
  • IsNavigationTarget: 调用以确定此实例是否可以处理导航请求。否则新建实例
  • OnNavigatedFrom: 当导航离开当前页时, 类似打开A, 再打开B时, 该方法被触发。

INavigationAware 执行流程

获取导航请求参数

正如上面所描述, 导航中允许我们传递参数, 用于在我们完成导航之前, 进行做对应的逻辑业务处理。这时候, 我们便可以在OnNavigatedTo方法中通过导航上下文中获取到传递的所有参数。如下:

        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            var id = navigationContext.Parameters.GetValue<int>("id");

            var name = navigationContext.Parameters["Name"].ToString();
        }

IConfirmNavigationRequest

该接口继承于INavigationAware, 所以, 它多了一个功能: 允许用户针对导航请求进行拦截。

    //多了一个回调函数, 该值觉得是否拦截该导航请求
    void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback);

IConfirmNavigationRequest 执行流程

拦截导航请求

当打开新的导航时, 或许有些情况下你需要经过用户进行确认, 这个时候, IConfirmNavigationRequest接口可以满足需求, 如下:

        public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        {
            bool result = true;

            if (MessageBox.Show("确认导航?", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.No)
                result = false;

            //通过回调当前返回的确认结果,决定是否启动该导航
            continuationCallback(result);
        }

导航日志, 其实就是对导航系统的一个管理功能, 理论上来说, 我们应该知道我们上一步导航的位置、以及下一步导航的位置, 包括我们导航的历史记录。以便于我们使用导航对应用程序可以灵活的控制。

IRegionNavigationJournal

该接口包含以下功能:

  • GoBack() : 返回上一页
  • CanGoBack : 是否可以返回上一页
  • GoForward(): 返回后一页
  • CanGoForward : 是否可以返回后一页

1.示例(返回上一页)

当导航日志当中,包含上一页的历史记录, 如下所示, D的前面有ABC的记录,所以对于D而言, 它可以返回上一页, 所以CanGoBack 为True。

2.示例(返回下一页)

当导航日志当中,包含下一个的历史记录,如下所示,D的后面有E的记录,所以对于D而言,它可以返回下一页,所以CanGoForward 为True。

示例

 MainWindow代码

<Window
    x:Class="PrismApp.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:PrismApp"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:prism="http://prismlibrary.com/"
    Title="{Binding Title}"
    Width="800"
    Height="450"
    prism:ViewModelLocator.AutoWireViewModel="True"
    mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*" />
            <RowDefinition Height="9*" />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal">
            <Button
                MinWidth="80"
                Margin="3"
                Command="{Binding OpenCommand}"
                CommandParameter="ViewA"
                Content="打开模块A"
                FontSize="12" />
            <Button
                MinWidth="80"
                Margin="3"
                Command="{Binding OpenCommand}"
                CommandParameter="ViewB"
                Content="打开模块B"
                FontSize="12" />
            <Button
                MinWidth="80"
                Margin="3"
                Command="{Binding OpenCommand}"
                CommandParameter="ViewC"
                Content="打开模块C"
                FontSize="12" />

            <Button
                MinWidth="80"
                Margin="3"
                Background="Yellow"
                Command="{Binding BackCommand}"
                Content="上页"
                FontSize="12" />
            <Button
                MinWidth="80"
                Margin="3"
                Background="Yellow"
                Command="{Binding ForwardCommand}"
                Content="下页"
                FontSize="12" />
        </StackPanel>
        <ContentControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>

绑定两个导航命令

            <Button
                MinWidth="80"
                Margin="3"
                Background="Yellow"
                Command="{Binding BackCommand}"
                Content="上页"
                FontSize="12" />
            <Button
                MinWidth="80"
                Margin="3"
                Background="Yellow"
                Command="{Binding ForwardCommand}"
                Content="下页"
                FontSize="12" />

MainWindouViewModle代码

namespace PrismApp.ViewModels
{
    internal class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism App";   //标题
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        private readonly IRegionManager regionManager;
        private IRegionNavigationJournal journal;           //导航日志

        public DelegateCommand<string> OpenCommand { get; private set; }
        public DelegateCommand BackCommand { get; private set; }
        public DelegateCommand ForwardCommand { get; private set; }

        public MainWindowViewModel(IRegionManager regionManager)  
        {
            BackCommand = new DelegateCommand(Back);
            ForwardCommand = new DelegateCommand(Forward);
            OpenCommand = new DelegateCommand<string>(Open);
            this.regionManager = regionManager;
        }

        private void Forward()
        {
            if (this.journal != null && journal.CanGoForward)
                journal.GoForward();
        }

        private void Back()
        {
            if (this.journal != null && journal.CanGoBack)
                journal.GoBack();
        }

        private void Open(string obj)//页面切换方法
        {
            
            NavigationParameters keys = new NavigationParameters();//传递参数
            keys.Add("Title", "Hello!");
            keys.Add("Name", "Tom!");
            //不带参数
            // regionManager.Regions["ContentRegion"].RequestNavigate(obj,keys);

            //带参数
            regionManager.Regions["ContentRegion"].RequestNavigate(obj, callBack =>
             {
                 if ((bool)callBack.Result)
                 {
                     journal = callBack.Context.NavigationService.Journal;
                 }
             }, keys);
        }
    }
}

ModuleA代码

ModuleA前端代码,主要绑定一个标题属性用于显示接收的参数

<UserControl x:Class="ModuleA.Views.ViewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ModuleA.Views"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="500"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True" >
    <Grid Background="AliceBlue">
        <TextBlock Text="{Binding Title}" FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</UserControl>

ViewAViewModel代码

namespace ModuleA.ViewModels
{
    public class ViewAViewModel : BindableBase, INavigationAware
    {
        public ViewAViewModel()
        {

        }

        private string title;

        public string Title
        {
            get { return title; }
            set { title = value; RaisePropertyChanged(); }
        }

        /// <summary>m
        /// 调用以确定此实例是否可以处理导航请求。否则新建实例
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <returns></returns>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return false;
        }


        /// <summary>
        /// 当导航离开当前页时, 类似打开A, 再打开B时, 该方法被触发。
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
            
        }

        /// <summary>
        /// 导航完成前, 此处可以传递过来的参数以及是否允许导航等动作的控制。
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            if (navigationContext.Parameters.ContainsKey("Title"))
            {
                Title = navigationContext.Parameters.GetValue<string>("Title");
            }
        }

        ///// <summary>
        ///// IConfirmNavigationRequest该接口继承于INavigationAware, 所以, 它多了一个功能: 允许用户针对导航请求进行拦截。
        ///// </summary>
        ///// <param name="navigationContext"></param>
        ///// <param name="continuationCallback"></param>
        //public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        //{
        //    bool result = true;
        //    if (MessageBox.Show("确认导航", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.No)
        //        result = false;
        //    //通过回调当前返回的确认结果,决定是否启动该导航
        //    continuationCallback(result);
        //}
    }
}

其他参考Prism框架(2)—Module的使用

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值