Prism之Region(2)

Prism之Region(1)中,介绍了一些Prism中页面组织以及切换的方式。这一篇将以一个很简单的示例程序来实践一下。

源码下载

下面是效果图:

image

先说Log,Prism内置了ILogFacade接口,在Prism提供的QuickStart项目里的Modularity中,有一个CallbackLogger,这里我们直接拿过来使用。然后在PrismRegionShell中放一个TextBox,将log的内容显示在这个TextBox中。值得一提的是,为了让输出新log的直接显示出来,需要将TextBox的滚动条滚动到最下面。这里采用的是如下方法:

?
1
2
3
4
5
6
public void Log( string message, Category category, Priority priority)
{
     this .LogContainer.Text += string .Format(CultureInfo.CurrentUICulture, "[{0}][{1}] {2}\r\n" , category, priority, message);
     //  这段代码的作用是让文本框的滚动条滚动到最底部
     LogContainer.Select(LogContainer.Text.Length, LogContainer.Text.Length);
}

然后说一下左边的导航区。这里放置了一个ItemsControl,并将其设为Region。里面的两个按钮并不是直接写死到xaml里的,而是在两个Module初始化时动态添加进来的。也就是说,这个ItemsControl并不知道自己将要包含哪些项。这里我们使用IRegionManager.RegisterViewWithRegion(RegionNames.NavRegion, typeof(EmptyNavigationItem));这种方式来将视图注册到Region中。这样当该Region显示的时候两个视图才会被初始化。这里需要注意的是,一个Region里需要同时显示多个视图时,视图的顺序问题。比如ItemsControl,哪个先被注册就哪个显示在上面,但是由于Module的加载速度等原因,所以这时两个视图不一定谁在上面。现在我需要指定[导航示例]这个按钮在上,那么Prism为我们提供了ViewSortHintAttribute来解决这个问题。在需要进行排序的视图上添加上相应的attribute就可以了。

?
1
2
3
4
5
[ViewSortHint( "01" )]
public partial class NavigationItem : UserControl
 
[ViewSortHint( "02" )]
public partial class EmptyNavigationItem : UserControl

在初始化导航实例的Module时,将导航示例的视图注册到内容区的Region,这时[上一个]按钮依然处于灰色状态,因为通过RegisterViewWithRegion方法显示的页面是不被记录的。当点击[ViewA][ViewB][ViewC]这三个按钮时,会采用RequestNavigate方法来进行页面的跳转,这时页面跳转的过程会被记录下来,此时就可以通过[上一个]和[下一个]按钮进行页面的前进和后退。

?
1
2
3
4
5
6
7
8
9
10
11
12
void ToSpecifiedView( string viewName)
{
     UriQuery query = new UriQuery();
     if (viewName == ViewNames.ViewA)
     {
         query.Add( "Time" , DateTime.Now.ToShortTimeString());
     }
     Uri uri = new Uri(viewName + query.ToString(), UriKind.Relative);
     _regionManager.RequestNavigate(RegionNames.NavDemoShowRegion, uri);
     logger.Log( "跳转到视图 [" + viewName + "]" , Category.Info, Priority.Low);
     ResetNavigationButtonState();
}

注意这三个视图已经在初始化Module的时候使用IUnityContainer.RegisterType<object, ViewA>(ViewNames.ViewA)方法注册过了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public void Initialize()
{
     logger.Log( "初始化Navigation模块" , Category.Debug, Priority.Low);
     _regionManager.RegisterViewWithRegion(RegionNames.NavRegion, typeof (NavigationItem));
     _regionManager.RegisterViewWithRegion(RegionNames.MainRegion,
                                             () => _container.Resolve<NavigationContainer>() );
     _regionManager.RegisterViewWithRegion(RegionNames.NavDemoActionRegion, typeof (ActionController));
 
     //  注意注册的类型的必须是object,因为Prism无法确定视图的类型,所以就用了object
     _container.RegisterType< object , ViewA>(ViewNames.ViewA);
     _container.RegisterType< object , ViewB>(ViewNames.ViewB);
     _container.RegisterType< object , ViewC>(ViewNames.ViewC);
}

ViewA和ViewB都实现了INavigationAware接口,不同之处在于ViewA是在其对应的ViewModel ViewAViewModel类中实现的,而ViewB则直接在Code Behind中实现的。Prism对MVVM提供了良好的支持,因此既可以选择在视图中实现该接口也可以在对应的ViewModel中实现。

?
1
2
3
4
public bool IsNavigationTarget(NavigationContext navigationContext)
{
     return false ;
}

在ViewB中,IsNavigationTarget方法返回了false,而ViewA中则返回了true。可以通过点击三个按钮进行页面跳转,观察log可以发现,ViewA只创建了一次,而ViewB则每次都要重新创建。还有就是在跳转到ViewA的时候传递了参数,可以在OnNavigatedTo方法中取出参数。

?
1
2
3
4
5
6
public void OnNavigatedTo(NavigationContext navigationContext)
{
     UriQuery query = navigationContext.Parameters;
     string time = query[ "Time" ];
     logger.Log( string .Format( "ViewA: 现在时间 {0}" , time), Category.Info, Priority.Medium);
}

源码下载

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值