WPF MVVM框架------ Prism中的区域和导航(二)

接着上一节,记录导航功能

准备工作

  • 1. 在ViewModels中新建两个视图对应的ViewModel类(RegionFirstViewModel.cs和RegionSecondViewModel.cs),如图所示

 

  •  2. 将视图与对应的ViewModel绑定

打开 App.xaml.cs 在重写的方法RegisterTypes中进行上下文对应

public partial class App : PrismApplication
{
    protected override Window CreateShell()
    {
        return Container.Resolve<RegionManageView>();
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.RegisterForNavigation<RegionFirstView, RegionFirstViewModel>();
        containerRegistry.RegisterForNavigation<RegionSecondView, RegionSecondViewModel>();
    }
}

实现对应的ViewModel

1.RegionFirstViewModel

因为需要将内容显示在界面上,实现通知效果,所以该类需要继承BindableBase,当我们导航到该界面并且想要带一些参数进来,或者想要阻拦当页面跳转到其他页面时,还以要实现IConfirmNavigationRequest接口

 1.1 创建一个Name属性,用于显示传递的参数,需要通知到界面上,所以要调用 RaisePropertyChanged()方法,

private string _name;

public string Name
{
    get { return _name; }
    set { _name = value; RaisePropertyChanged(); }
}

1.2 继承IConfirmNavigationRequest,需要实现方法

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

public void OnNavigatedFrom(NavigationContext navigationContext)
{ 
    Uri uri = navigationContext.Uri;
}

public void OnNavigatedTo(NavigationContext navigationContext)
{
    Name = navigationContext.Parameters["Name"]?.ToString();//获取传递的参数
}

public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
{
    bool isOk = false;
    if (MessageBox.Show("确定跳转吗?", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
    {
        isOk = true;
    }
    continuationCallback(isOk);
}
方法 public void IsNavigationTarget(NavigationContext navigationContext)
  表示是否重用该实例,返回false时,将会重新new一个新的实例出来,若返回true,则重用原来的实例

方法 public void OnNavigatedFrom(NavigationContext navigationContext):
  当要导航到其他页面之前,会执行该方法,离开该页面之前想要做的事情可以放在该页面 ,参数navigationContext中包含即将导航到的目标页面Uri
方法 public void OnNavigatedTo(NavigationContext navigationContext):
  
导航到该页面时,会直接进入该方法,可以从navigationContext的Parameters中拿到传递过来的数据,Parameters是以键值对的方式传递参数的,所以可以按照上面的方法获取值
方法 public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback):
  
当要导航到其他页面时,会首先进入该方法,在这个方法中可以进行拦截或者说是给一个再次确认的机会,调用委托传入true,则可以导航,传入false时则会阻止导航到其他页面
1.3 RegionFirstViewModel 完整代码
public class RegionFirstViewModel : BindableBase, IConfirmNavigationRequest
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set { _name = value; RaisePropertyChanged(); }
    }

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

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
        Uri uri = navigationContext.Uri;
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
        Name = navigationContext.Parameters["Name"]?.ToString();//获取传递的参数
    }

    public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
    {
        bool result = false;
        if (MessageBox.Show("确定跳转吗?", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
        {
            result = true;
        }

        continuationCallback(result);
    }
}

2. RegionSecondViewModel

public class RegionSecondViewModel : INavigationAware
{
    public bool IsNavigationTarget(NavigationContext navigationContext)
    {
        return true;
    }

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
    }
}

3. 接口 IConfirmNavigationRequestINavigationAware

  其实IConfirmNavigationRequest也继承了INavigationAware,只是IConfirmNavigationRequest多了一个确认导航到其他页面的方法。可以进行再次确认

 

 

 传递参数以及记录导航

1.修改主页面

打开主窗体 RegionManageView ,添加两个按钮(向前导航和向后导航),并绑定GoForwardCommand和GoBackCommand

 

 

<Button Height="25"
    Content="GoForward"
    Command="{Binding GoForwardCommand}"
    CommandParameter="RegionSecondView" />
<Button Height="25"
    Content="GoBack"
    Command="{Binding GoBackCommand}"
    CommandParameter="RegionSecondView" />

 

2. 传递参数和记录导航

  声明一个字段来保存导航记录   private IRegionNavigationJournal journal;

       修改private void DoOpenRegionCommand(string obj)方法   其中keyValuePairs就是传递的参数,journal = callBack.Context.NavigationService.Journal则是导航记录

private void DoOpenRegionCommand(string obj)
{
    NavigationParameters keyValuePairs = new()
    {
        { "Name", obj }
    };
    regionManager.Regions["MainContent"].RequestNavigate(obj, callBack =>
    {
         if ((bool)callBack.Result)
         {
             journal = callBack.Context.NavigationService.Journal;
         }
    }, keyValuePairs);
}

3. 实现向前导航和向后导航命令

private void DoGoForwardCommand()
{
    journal?.GoForward();
}

private void DoGoBackCommand()
{
    journal?.GoBack();
}

4. 完整主窗体代码

RegionManageView.xalm

<Window x:Class="MvvmBase.PrismDemo.Views.RegionManageView"
        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:MvvmBase.PrismDemo.Views"
        xmlns:prism="http://prismlibrary.com/"
        mc:Ignorable="d"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="RegionManageView"
        Height="450"
        Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <StackPanel Width="150">
            <Button Height="25"
                    Content="OpenRegionFirstView"
                    Command="{Binding OpenRegionCommand}"
                    CommandParameter="RegionFirstView" />
            <Button Height="25"
                    Content="OpenRegionSecondView"
                    Command="{Binding OpenRegionCommand}"
                    CommandParameter="RegionSecondView" />
            <Button Height="25"
                    Content="CloseRegionFirstView"
                    Command="{Binding CloseRegionCommand}"
                    CommandParameter="RegionFirstView" />
            <Button Height="25"
                    Content="CloseRegionSecondView"
                    Command="{Binding CloseRegionCommand}"
                    CommandParameter="RegionSecondView" />
            <Button Height="25"
                    Content="GoForward"
                    Command="{Binding GoForwardCommand}"
                    CommandParameter="RegionSecondView" />
            <Button Height="25"
                    Content="GoBack"
                    Command="{Binding GoBackCommand}"
                    CommandParameter="RegionSecondView" />
        </StackPanel>
        <ContentControl Grid.Column="1"
                        prism:RegionManager.RegionName="MainContent" />
    </Grid>
</Window>

RegionManageViewModel.cs

public class RegionManageViewModel : BindableBase
{
    private readonly IRegionManager regionManager;
    private IRegionNavigationJournal journal;

    public DelegateCommand<string> OpenRegionCommand { get; private set; }
    public DelegateCommand<string> CloseRegionCommand { get; private set; }
    public DelegateCommand GoForwardCommand { get; private set; }
    public DelegateCommand GoBackCommand { get; private set; }

    public RegionManageViewModel(IRegionManager regionManager)
    {
        OpenRegionCommand = new DelegateCommand<string>(DoOpenRegionCommand);
        CloseRegionCommand = new DelegateCommand<string>(DoCloseRegionCommand);
        GoForwardCommand = new DelegateCommand(DoGoForwardCommand);
        GoBackCommand = new DelegateCommand(DoGoBackCommand);
        this.regionManager = regionManager;
    }

    private void DoGoForwardCommand()
    {
        journal?.GoForward();
    }

    private void DoGoBackCommand()
    {
        journal?.GoBack();
    }

    private void DoCloseRegionCommand(string obj)
    {
        var views = regionManager.Regions["MainContent"];
        var view = views.Views.FirstOrDefault(it => it.GetType().Name == obj);
        if (view != default)
        {
            views.Remove(view);
        }
    }

    private void DoOpenRegionCommand(string obj)
    {
        NavigationParameters keyValuePairs = new()
        {
            { "Name", obj }
        };
        regionManager.Regions["MainContent"].RequestNavigate(obj, callBack =>
        {
             if ((bool)callBack.Result)
             {
                 journal = callBack.Context.NavigationService.Journal;
             }
        }, keyValuePairs);
    }
}

 

 

 

 

 

Parameters
posted @ 2023-02-23 20:33  just--like  阅读(808)  评论(0编辑  收藏  举报