silverlight 学习笔记 (九):Prism与MVVM模式在silverlight中的应用

首先记录一个错误的解决办法,在使用Prism中在新增的Module中添加

Microsoft.Practices.Prism.MefExtensions的引用时需要注意将其“复制本地”改为false,否则会报以下错误:

An exception occurred while initializing module 'Module1'.
    - The exception message was: 撰写保持不变。由于以下错误,更改被拒绝: 撰写生成多个撰写错误,具有 15 个根本原因。下面提供了根本原因。 有关详细信息,请检查 CompositionException.Errors 属性

 回到正题,在silverlight中最常见得开发模式是MVVM+Prism+WCF RIA,通过前面的学习已基本账务了MVVM架构,至于WCF RIA需要学习的是EF以及我们需要灵活掌握异步开发模式。下面以实例说明一个简单的MVVM+Prism的架构。

首先理下思路:

1、利用前面学习的知识建立Bootstrapper ,并建立加载Shell,在Shell中布局Region

2、在Bootstrapper中重载CreateModuleCatalog方法,确定Module加载。

3、创建Module(刚学silverlight时习惯建立silverlight类库,而类库是无法形成xap),新建module的加载类,注意在该加载类中的属性标示名称需要和我们前面定义加载的xaml配置文件的module名称一致

[ModuleExport("Module1"typeof(Module1))]

4、在新的Module中新增View,ViewModel,在View中建立与ViewModel绑定关系

5、在Module加载类的初始化接口函数中指定Module初始加载的视图到指定的Region中

6、再次以代码验证上节说介绍的有关Export,Import,这将会在View、ViewModel中应用,同时需要掌握有关于如何灵活的将View注册到对应的Region中

到此基本上可以利用Prism对模块进行动态加载,同时如果将View注入到对应的Region中,而至于MVVM与原先的模式没有太多变化,只是更多的用到了MEF注入。下面需要研究思考的是关于Module之间如果通信的问题了,可以好好考虑学习下利用IEventAggregator 来实现模块间事件的订阅与发布,似乎有点类似于MVVM中的Messager了。

在基本理清了思路后,接下来做些简单的代码说明

1、Bootstrapper类

 

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Practices.Prism.MefExtensions;
using System.ComponentModel.Composition.Hosting;

namespace Prism.MVVM.Test
{
    /// <summary>
    
/// 将MefExtensions的引用复制模式修改为false
    
/// 很重要
    
/// </summary>
    public class Bootstrapper:MefBootstrapper
    {
        /// <summary>
        
/// 创建Shell,从Container中获取注入的Shell实例
        
/// </summary>
        
/// <returns></returns>
        protected override DependencyObject CreateShell()
        {
            return this.Container.GetExportedValue<Shell>();
        }
        /// <summary>
        
/// 初始化Shell,设置启动界面为ShellView
        
/// </summary>
        protected override void InitializeShell()
        {
            base.InitializeShell();
            App.Current.RootVisual = (UIElement)this.Shell;
        }

        /// <summary>
        
/// 将自身添加到目录中,很重要,否则系统启动会报错
        
/// </summary>
        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
            
        }
        /// <summary>
        
/// 可建立xaml文件配置加载模块
        
/// </summary>
        protected override Microsoft.Practices.Prism.Modularity.IModuleCatalog CreateModuleCatalog()
        {
            return
                Microsoft.Practices.Prism.Modularity.ModuleCatalog.CreateFromXaml(new Uri("/Prism.MVVM.Test;component/ModulesCatalog.xaml",
                                                                                          UriKind.Relative));

        }

        protected override CompositionContainer CreateContainer()
        {
            var container = base.CreateContainer();
            CompositionHost.Initialize(container);
            return container;
        }
       
        

    }
}

2、Shell布局,在该布局中主要用了ControlControl,如配合使用telerik下的RadTransitionControl 将会有更好的动画效果展现

<UserControl x:Class="Prism.MVVM.Test.Shell"
    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:prism="clr-namespace:Microsoft.Practices.Prism.Regions;assembly=Microsoft.Practices.Prism"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="#FFE2E25E">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="104*" />
            <ColumnDefinition Width="296*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="62*" />
            <RowDefinition Height="238*" />
        </Grid.RowDefinitions>
        <Border BorderBrush="Silver" BorderThickness="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" Margin="0" Name="border1" VerticalAlignment="Stretch" Background="#FF4848B9">
            <ContentControl Name="contentControl1" prism:RegionManager.RegionName="MainTitleRegion" />
        </Border>
        <Border BorderBrush="Silver" BorderThickness="1" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Stretch" Margin="0" Name="border2" VerticalAlignment="Stretch" CornerRadius="5" Background="#FF0B418F">
            <ContentControl Name="contentControl3" prism:RegionManager.RegionName="MainContentRegion" />
        </Border>
        <Border BorderBrush="Silver" BorderThickness="1" Grid.Row="1" HorizontalAlignment="Stretch" Name="border3" VerticalAlignment="Stretch" CornerRadius="5" Background="#FF0B418F">
            <ContentControl Name="contentControl2" prism:RegionManager.RegionName="MainNavRegion" />
        </Border>

    </Grid>
</UserControl>

 3、module加载

View Code
 1 using System;
 2 using System.Net;
 3 using System.Windows;
 4 using System.Windows.Controls;
 5 using System.Windows.Documents;
 6 using System.Windows.Ink;
 7 using System.Windows.Input;
 8 using System.Windows.Media;
 9 using System.Windows.Media.Animation;
10 using System.Windows.Shapes;
11 using Microsoft.Practices.Prism.Modularity;
12 using Microsoft.Practices.Prism.MefExtensions.Modularity;
13 using Microsoft.Practices.Prism.Regions;
14 using System.ComponentModel.Composition;
15 using Module1.View;
16 using Microsoft.Practices.ServiceLocation;
17 
18 namespace Module1
19 {
20     [ModuleExport("Module1"typeof(Module1))]
21     public class Module1 : IModule, IPartImportsSatisfiedNotification 
22     {
23         [Import]
24         public IRegionManager regionManager;
25         public void Initialize()
26         {
27             var titleview = ServiceLocator.Current.GetInstance(typeof(TitleView), "TitleView");
28             var navView = ServiceLocator.Current.GetInstance(typeof(NavView), "NavView");
29             this.regionManager.RegisterViewWithRegion(RegionNames.MainTitleRegion, () => { return ServiceLocator.Current.GetInstance(typeof(TitleView), "TitleView"); });
30             if (this.regionManager.Regions[RegionNames.MainNavRegion].GetView("NavView")==null)
31                 this.regionManager.Regions[RegionNames.MainNavRegion].Add(navView);
32             this.regionManager.RequestNavigate(RegionNames.MainContentRegion, "DefaultContentView");
33         }
34 
35         public void OnImportsSatisfied()
36         {
37             //throw new NotImplementedException();
38         }
39     }
40 }

4、创建View,ViewModel

 

View Code
 1 [Export("TitleView")]
 2     public partial class TitleView : UserControl
 3     {
 4         public TitleView()
 5         {
 6             InitializeComponent();
 7         }
 8         [Import("TitleViewModel")]
 9         public TitleViewModel ViewModel { get { return this.DataContext as TitleViewModel; } set { this.DataContext = value; } }
10     }

 

View Code
 1 using System;
 2 using System.Net;
 3 using System.Windows;
 4 using System.Windows.Controls;
 5 using System.Windows.Documents;
 6 using System.Windows.Ink;
 7 using System.Windows.Input;
 8 using System.Windows.Media;
 9 using System.Windows.Media.Animation;
10 using System.Windows.Shapes;
11 using System.ComponentModel.Composition;
12 
13 namespace Module1.ViewModel
14 {
15     [Export("TitleViewModel")]
16     public class TitleViewModel
17     {
18         public string ProjectName { get { return "我的测试项目"; } }
19     }
20 }

 

 

原文地址:https://www.cnblogs.com/oldkingsir/p/2367330.html