首页 > 其他分享 >Wpf Prism 导航(参数传递,路由守卫,路由记录)

Wpf Prism 导航(参数传递,路由守卫,路由记录)

时间:2023-12-04 10:01:19浏览次数:22  
标签:void private Prism navigationContext 跳转 using Wpf public 路由

十年河东,十年河西,莫欺少年穷

学无止境,精益求精

1、新建项目wpfApp5,添加Nuget引用,并初始化App.xaml 及 cs 类

Wpf Prism 导航(参数传递,路由守卫,路由记录)_microsoft

 app.xaml 如下:

<Prism:PrismApplication x:Class="WpfApp5.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApp5"
             xmlns:Prism="http://prismlibrary.com/"  
                        >
    <Application.Resources>
         
    </Application.Resources>
</Prism:PrismApplication>

View Code

cs 类如下:

using DryIoc;
using Prism.DryIoc; 
using Prism.Ioc;
using Prism.Modularity;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using WpfApp5.UserControls;
using WpfApp5.UserControls.Models;
using WpfApp5.Views;

namespace WpfApp5
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            //设置启动窗体为MainView
            return Container.Resolve<MainView>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<viewA, viewAModel>();////如果不声明名字为viewA , 默认和类名一致
            containerRegistry.RegisterForNavigation<viewB, viewBModel>("viewB");////如果不声明名字为viewB , 默认和类名一致
            containerRegistry.RegisterForNavigation<viewC, viewCModel>();////如果不声明名字为viewC , 默认和类名一致
        }
    }
}

View Code

说明:

xaml 中引入 Prism

xmlns:Prism="http://prismlibrary.com/"

更改标签为:

<Prism:PrismApplication> 。。。。。。 </Prism:PrismApplication>

设置启动窗体为 MainView,这里需要说明的是:窗体必须放在Views文件夹下而且必须以View结尾,ViewModel必须放在ViewModels文件夹下面,文件必须以ViewModel结尾。

App.xaml.cs 中注册了三个导航窗体(用户控件),分别为:viewA、viewB、viewC,及启动窗体MainView

2、声明 MainView 

新建文件夹 Views 和 数据上下文文件夹 ViewModels,在Views文件夹中新建 MainView窗体(必须以View结尾),在ViewModels文件夹中新建 MainViewModel 上下文类(必须以Model结尾)

MainView.xaml 如下

<Window x:Class="WpfApp5.Views.MainView"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp5.Views" 
        xmlns:Prism="http://prismlibrary.com/"  
        Prism:ViewModelLocator.AutoWireViewModel="True"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal">
            <Button Content="viewA" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewA"></Button>
            <Button Content="viewB" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewB"></Button>
            <Button Content="viewC" Margin="5" Height="35" Width="100" Command="{Binding BtnCommand}" CommandParameter="viewC"></Button>
            <Button Content="返回上一页" Margin="5" Height="35" Width="100" Command="{Binding BtnBack}"></Button>
            <Button Content="返回下一页" Margin="5" Height="35" Width="100" Command="{Binding BtnForward}"></Button>
        </StackPanel>

        <ContentControl Grid.Row="1" Prism:RegionManager.RegionName="ContentRegion"/>
    </Grid>
</Window>

View Code

Wpf Prism 导航(参数传递,路由守卫,路由记录)_xml_02

 viewModel 类如下

public class MainViewModel : BindableBase
    {
        public DelegateCommand<string> BtnCommand { get; private set; }
        public DelegateCommand BtnBack { get; private set; }
        public DelegateCommand BtnForward { get; private set; }
        /// <summary>
        /// 区域管理器-跳转相关
        /// </summary>
        private readonly IRegionManager regionManager;
        /// <summary>
        /// 用于保存路由跳转记录
        /// </summary>
        private  IRegionNavigationJournal journal;

        public MainViewModel(IRegionManager regionManager)
        {
            BtnCommand = new DelegateCommand<string>(BtnRedirect);
            BtnBack = new DelegateCommand(Back);
            BtnForward = new DelegateCommand(Forward);
            this.regionManager = regionManager;
        }

        /// <summary>
        /// 页面跳转
        /// </summary>
        /// <param name="parma"></param>
        private void BtnRedirect(string parma)
        {
            NavigationParameters keys = new NavigationParameters();
            keys.Add("name", "河南大学");
            keys.Add("id", "58");
            regionManager.Regions["ContentRegion"].RequestNavigate(parma,navigationCallback, keys);
        }

        private void navigationCallback(NavigationResult  navigation)
        {
            if (navigation.Result.Value)
            {
                //如果跳转成功,则存储跳转记录
                journal = navigation.Context.NavigationService.Journal;
            }
        }

        /// <summary>
        /// 返回上一页
        /// </summary>
        private void Back()
        {
            if (journal.CanGoBack)
            {
                journal.GoBack();
            }
        }

        /// <summary>
        /// 返回下一页
        /// </summary>
        private void Forward()
        {
            if (journal.CanGoForward)
            {
                journal.GoForward();
            }
        }
    }

View Code

说明如下:

必须继承自 BindableBase

public class MainViewModel : BindableBase

声明按钮命令事件、区域管理、路由

public DelegateCommand<string> BtnCommand { get; private set; }
        public DelegateCommand BtnBack { get; private set; }
        public DelegateCommand BtnForward { get; private set; }
        /// <summary>
        /// 区域管理器-跳转相关
        /// </summary>
        private readonly IRegionManager regionManager;
        /// <summary>
        /// 用于保存路由跳转记录
        /// </summary>
        private  IRegionNavigationJournal journal;

        public MainViewModel(IRegionManager regionManager)
        {
            BtnCommand = new DelegateCommand<string>(BtnRedirect);
            BtnBack = new DelegateCommand(Back);
            BtnForward = new DelegateCommand(Forward);
            this.regionManager = regionManager;
        }

带有参数的页面跳转如下:

/// <summary>
        /// 页面跳转-带有参数
        /// </summary>
        /// <param name="parma"></param>
        private void BtnRedirect(string parma)
        {
            NavigationParameters keys = new NavigationParameters();
            keys.Add("name", "河南大学");
            keys.Add("id", "58");
            regionManager.Regions["ContentRegion"].RequestNavigate(parma,navigationCallback, keys);
        }

        private void navigationCallback(NavigationResult  navigation)
        {
            if (navigation.Result.Value)
            {
                //如果跳转成功,则存储跳转记录
                journal = navigation.Context.NavigationService.Journal;
            }
        }

navigationCallback 为回调事件,用于记录导航

返回上一页、下一页代码如下:

/// <summary>
        /// 返回上一页
        /// </summary>
        private void Back()
        {
            if (journal.CanGoBack)
            {
                journal.GoBack();
            }
        }

        /// <summary>
        /// 返回下一页
        /// </summary>
        private void Forward()
        {
            if (journal.CanGoForward)
            {
                journal.GoForward();
            }
        }

3、用户控件 viewA  (无需遵守Prism的规则)

xaml 如下:

<UserControl x:Class="WpfApp5.UserControls.viewA"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp5.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock Text="I am viewA" FontSize="24"/>
            <TextBlock Text="{Binding Name}" FontSize="24"/>
            <TextBlock Text="{Binding Id}" FontSize="24"/>
        </StackPanel>
    </Grid>
</UserControl>

绑定的Name 和 Id 为参数传递的值

viewModel类如下:

public class viewAModel : BindableBase, INavigationAware, IConfirmNavigationRequest
    { 
        public viewAModel()
        {

        }

        private string name;
        public string Name
        {
            get { return this.name; }
            set
            {
                name = value;
                RaisePropertyChanged();
            }
        }
        private string id;
        public string Id
        {
            get { return this.id; }
            set
            {
                id = value;
                RaisePropertyChanged();
            }
        }


        /// <summary>
        /// 路由保卫--可以在此方法中判断是否允许跳转--continuationCallback 会通知 OnNavigatedFrom 方法是否跳转
        /// </summary>
        /// <param name="navigationContext"></param>
        public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        {
            var isok = false;
            if (MessageBox.Show("确定跳转吗", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                isok = true;
            }
            continuationCallback(isok);
        }

       

        /// <summary>
        /// 进入该viewModel时,是否创建新的viewModel对象
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <returns></returns>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

        /// <summary>
        /// 离开该viewModel执行 和 路由保卫配合使用
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
             //离开时 可能会涉及到一些数据处理,在此不做演示
        }

        /// <summary>
        /// 进入该viewModel时执行
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            if (navigationContext.Parameters.ContainsKey("name"))
            {
                this.Name = navigationContext.Parameters.GetValue<string>("name");
            }
            if (navigationContext.Parameters.ContainsKey("id"))
            {
                this.Id = navigationContext.Parameters.GetValue<string>("id");
            }
        }
    }

View Code

说明如下:

继承自 BindableBase,INavigationAware, IConfirmNavigationRequest

public class viewAModel : BindableBase, INavigationAware, IConfirmNavigationRequest

BindableBase(用于双向绑定),INavigationAware(用于导航跳转), IConfirmNavigationRequest(用于导航跳转前,确认是否跳转,即路由保卫)

1、进入用户控件viewModel时执行

/// <summary>
        /// 进入该viewModel时执行
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            if (navigationContext.Parameters.ContainsKey("name"))
            {
                this.Name = navigationContext.Parameters.GetValue<string>("name");
            }
            if (navigationContext.Parameters.ContainsKey("id"))
            {
                this.Id = navigationContext.Parameters.GetValue<string>("id");
            }
        }

这里我们判断URL是否含有相关参数,有的话,则接收,赋值

2、进入该viewModel时,是否重新创建该viewmodle对象

/// <summary>
        /// 进入该viewModel时,是否创建新的viewModel对象
        /// </summary>
        /// <param name="navigationContext"></param>
        /// <returns></returns>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return true;
        }

3、离开viewMdoel时

/// <summary>
        /// 离开该viewModel执行 和 路由保卫配合使用
        /// </summary>
        /// <param name="navigationContext"></param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
             //离开时 可能会涉及到一些数据处理,在此不做演示
        }
        /// <summary>
        /// 路由保卫--可以在此方法中判断是否允许跳转--continuationCallback 会通知 OnNavigatedFrom 方法是否跳转
        /// </summary>
        /// <param name="navigationContext"></param>
        public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
        {
            var isok = false;
            if (MessageBox.Show("确定跳转吗", "温馨提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                isok = true;
            }
            continuationCallback(isok);
        }

ConfirmNavigationRequest 可以理解为路由保卫,用于判断是否可以跳转, continuationCallback 为回调函数,当它的参数为true时,则允许跳转,否则不跳转。

4、双向绑定

private string name;
        public string Name
        {
            get { return this.name; }
            set
            {
                name = value;
                RaisePropertyChanged();
            }
        }
        private string id;
        public string Id
        {
            get { return this.id; }
            set
            {
                id = value;
                RaisePropertyChanged();
            }
        }

注意使用 RaisePropertyChanged();方法即可

@天才卧龙的博客



标签:void,private,Prism,navigationContext,跳转,using,Wpf,public,路由
From: https://blog.51cto.com/u_15316082/8673524

相关文章

  • Wpf 第三方Mvvm包(mvvmLight/Microsoft.Toolkit.Mvvm/CommunityToolkit.Mvvm)
    十年河东,十年河西,莫欺少年穷学无止境,精益求精 mvvmLight和 Microsoft.Toolkit.Mvvm已被Nuget弃用且不再更新,在此不作说明CommunityToolkit.Mvvm是NetCore版本引用包,详情参考:WPFMVVM框架:CommunityToolkit.Mvvm包使用介绍1、wpf项目中使用 CommunityToolkit.Mvvm(NetCore3.1......
  • WPF 控件驱动控件 及 数据驱动控件(双向绑定)
    wpf双向绑定十年河东,十年河西,莫欺少年穷学无止境,精益求精最近在知乎,看了很多提问,涉及到就业,裁员,经济等,不看不知道,越看越头疼,知乎上很多人提问毕业生就业如何难,2023年裁员如何严重,35岁的中年危机,程序员被裁员后找不到工作该,经济如何差等话题哎,这让我这个35......
  • SpringCloud动态路由利器--router4j
    ​前言本文介绍Java的动态路由中间件:router4j。router4j用于SpringCloud项目,它可以将某个url请求路由到指定的机器上,也可以将所有请求强制转到指定机器。问题描述Java后端在开发SpringCloud项目时如果同一个应用起了多个实例,会遇到以下问题:无法将指定url请求强制转到个人电脑......
  • 【Docker】Linux路由连接两个不同网段namespace,连接namespace与主机
    如果两个namespace处于不同的子网中,那么就不能通过bridge进行连接了,而是需要通过路由器进行三层转发。然而Linux并未像提供虚拟网桥一样也提供一个虚拟路由器设备,原因是Linux自身就具备有路由器功能。路由器的工作原理是这样的:路由器上有2到多个网络接口,每个网络接口处于不同的三层......
  • 【Docker】从命名空间和路由角度探究Docker的bridge网络
    桥接网络是Docker的默认网络模式。在桥接网络中,Docker会为每个容器创建一个虚拟网络接口,并为容器分配一个IP地址。容器可以通过桥接网络与主机和其他容器进行通信,也能暴露端口供外部访问。容器之间的通信原理首先我们创建两个容器:$dockercontainerrun-d--rm--namebox1busyb......
  • 搭建Wpf框架(18) ——DataGrid实现右冻结
    19.搭建Wpf框架(18)——DataGrid实现右冻结先上效果图: 其中,Field3和Field4为右冻结列。将一下大致思路,1.在DataGrid右边再放一个DataGrid,用来显示右冻结的列,把冻结的列从左边的DataGrid移除。2.然后左边的DataGrid右侧的滚动条隐藏,横向滚动条显示,右边的DataDataGrid右侧......
  • 路由器拨号上网
       1电脑网线直连路由器上网口1-6随便一个,路由器的wan口链接学校的网线2电脑网页访问192.168.1.1  输入上网账号密码Ld5 设置wifi名字和密码完成自动开始链接查看状态 上不去多连接几次,选择正常拨号模式 确保电脑的时间和当前网络时间同步......
  • Wpf Prism初体验
    十年河东,十年河西,莫欺少年穷学无止境,精益求精1、项目引入 Prism.DryIoc  2、规则说明窗体必须放在Views文件夹下而且必须以View结尾,ViewModel必须放在ViewModels文件夹下面,文件必须以ViewModel结尾。在prism框架下,可以不为窗体设定数据上下文,但,在窗体中必须显示声明:......
  • WPF资源
    一、静态动态资源1.资源定义<Window.Resources><SolidColorBrushx:Key="SolidColor"Color="Red"/></Window.Resources> 2.资源使用:动态、静态<ButtonContent="button1"BorderBrush="{StaticRe......
  • WPF应用开发之控件动态内容展示
    在我们开发一些复杂信息的时候,由于需要动态展示一些相关信息,因此我们需要考虑一些控件内容的动态展示,可以通过动态构建控件的方式进行显示,如动态选项卡展示不同的信息,或者动态展示一个自定义控件的内容等等,目的就是能够减少一些硬编码的处理方式,以及能够灵活的展示数据。本篇随笔......