【Prism004】区域和导航

 

简介

导航被定义为应用程序协调用户与应用程序交互或内部应用程序状态更改导致的UI更改的过程。Region作为Prism模块化中的核心概念,目的是弱化模块之间的耦合关系。在我们开发应用程序时,界面上的区域往往是固定的,如常见的布局:Header、Menu、Content这样的区域布局。
核心概念:Region、RegionManager、RegionAdapter

注册区域

使用RegionManager类的附加属性RegionName来注册区域
<ContentControl prism:RegionManager.RegionName="RibbonRegion" DockPanel.Dock="Top">
 
或者使用RegionManager.SetRegionName(控件对象,“区域名称”)方法调用的方式来注册区域。
 

区域适配器

并不是所有控件都可以注册为区域的,如果定义区域的控件没有提供区域适配器,运行的时候会报错,Prism内置了几个区域适配器:
ContentControlRegionAdapter
ItemControlRegionAdapter
SelectorRegionAdapter
  • ComboBox
  • ListBox
  • Ribbon
  • TabControl

拓展区域适配器

1、定义适配器类
public class StackPanelRegionAdapter : RegionAdapterBase<StackPanel>
    {
        public StackPanelRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory) : base(regionBehaviorFactory)
        {
        }

        protected override void Adapt(IRegion region, StackPanel regionTarget)
        {
            region.Views.CollectionChanged += (s, e) =>
            {
                if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                {
                    foreach (FrameworkElement item in e.NewItems)
                    {
                        regionTarget.Children.Add(item);
                    }
                }
            };
        }

        protected override IRegion CreateRegion()
        {
            return new Region();
        }
    }
 
2、将适配器注册到系统中,App类中重写注册方法
protected override void ConfigureRegionAdapterMappings(RegionAdapterMappings regionAdapterMappings)
        {
            base.ConfigureRegionAdapterMappings(regionAdapterMappings);
            regionAdapterMappings.RegisterMapping(typeof(StackPanel), Container.Resolve<StackPanelRegionAdapter>());
        }
 
 

区域导航

  1. 基本区域导航(Basic Region Nagivation)

在Prism中,区域已经扩展,以支持基于URI和可扩展导航机制的更一般的导航概念。区域内导航意味着将在该区域内显示新视图。要显示的视图通过URI标识,默认情况下,URI指的是要创建的视图的名称。可以使用INavigateAsync接口定义的RequestNavigate方法以编程方式启动导航。
INavigateAsync接口由Region类实现,可以在该区域内启动导航。
IRegion mainRegion = ...;
mainRegion.RequestNavigate(new Uri("InboxView", UriKind.Relative));
 
也可以使用更简单的字符串重载:
IRegion mainRegion = ...;
mainRegion.RequestNavigate("InboxView");
 
还可以在RegionManager上调用RequestNavigate方法,该方法允许您指定要导航的区域的名称。默认情况下,导航URI指定在容器中注册的视图的名称。
IRegionManager regionManager = ...;
regionManager.RequestNavigate("MainRegion", new Uri("InboxView", UriKind.Relative));
 
或者
IRegionManager regionManager = ...;
regionManager.RequestNavigate("MainRegion", "InboxView");
 
  1. 导航确认(Confirming Navigation)

导航过程中,通常需要用户参与互动,以确保视图切换前,用户可以确认或者取消此次导航行为。
使用方式:ViewModel继承 IConfirmNavigationRequest
public class ViewAViewModel : BindableBase, IConfirmNavigationRequest
{
    public ViewAViewModel()
    {
    }

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

        // this is demo code only and not suitable for production. It is generally
        // poor practice to reference your UI in the view model. Use the Prism
        // IDialogService to help with this.
        if (MessageBox.Show("Do you to navigate?", "Navigate?", MessageBoxButton.YesNo) == MessageBoxResult.No)
            result = false;

        continuationCallback(result);
    }

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

    public void OnNavigatedFrom(NavigationContext navigationContext)
    {
    }

    public void OnNavigatedTo(NavigationContext navigationContext)
    {
    }
}
 
 
  1. 控制区域中视图的生命周期(Controlling View Lifetime)

在实例化、初始化新视图并将其添加到目标区域后,它将变为活动视图,而上一个视图将被停用。有时,您会希望从区域中删除停用的视图。Prism提供IRegionMemberLifetime接口,IRegionMemberLifetime接口允许您指定是从区域中删除已停用的视图,还是仅将其标记为已停用,从而控制区域内视图的生存期。
public class EmployeeDetailsViewModel : BindableBase, IRegionMemberLifetime
{
    public bool KeepAlive
    {
        get { return true; }
    }
}
 
IRegionMemberLifetime接口定义了一个只读属性KeepAlive。如果此属性返回false,则视图在停用时将从区域中删除。由于该区域不再具有对该视图的引用,因此它有资格进行垃圾收集(除非应用程序中的其他组件维护对它的引用)。可以在视图或视图模型类上实现此接口。尽管IRegionMemberLifetime接口主要用于允许您在激活和停用期间管理区域内视图的生存期,但在目标区域中激活新视图后的导航期间也会考虑KeepAlive属性。
或者使用特性标签的形式实现:
[RegionMemberLifetime(KeepAlive = true)]
public class EmployeeDetailViewModel : BindableBase
{
}

 

posted @ 2021-12-16 14:34  爱吃豆子  阅读(595)  评论(0)    收藏  举报