Author: 周银辉
1. 前提条件:
你需要下载到CAL (Composite application library ) 库,实际上就是几个DLL 文件,在项目中将会引用到他们来打造我们的程序,你可以从这里下载到它们。当然你也需要一个能打造WPF 应用的IDE ,比如VS2008 。
2 .创建Shell Project
2.1 .在VS 中新建一个WPF Application ,将CAL 库文件添加到项目引用中
2.2 .将自动生成的Window1 主窗口及其相应的文件重命名为Shell ,其将作为我们的Composite App 的Shell 。
2.3 .创建Bootstrapper ,自定义程序初始化方式
新建一个Bootstrapper 类,让其继承于Unity Bootstrapper ,并重写其中的某些方法来实现我们的定制
internal class Bootstrapper : UnityBootstrapper
{
protected override DependencyObject CreateShell()
{
var shell = new Shell();
shell.Show();
return shell;
}
protected override IModuleEnumerator GetModuleEnumerator()
{
return new StaticModuleEnumerator();
}
}
我们通过重写CreateShell() 方法指定我们的Shell ,通过重写GetModuleEnumerator() 方法来指定我们的模块加载方式(这里为了编译通过,我们暂时返回一个StaticModuleEnumerator ,待会会介绍如何使用配置文件来配置模块的加载)
2.4 .修改程序启动方式
我们知道当新建一个WPF Application 时,VS 会在App.xaml 自动生成指定StartupUri 到主窗口,但这不是我们的Composite WPF Application 想要的方式,我们需要从Bootstrapper 启动,所以删除App.xaml 自动生成指定的StartupUri ,并重写App 类的构造方法:
public partial class App
{
public App()
{
var bootStrapper = new Bootstrapper();
bootStrapper.Run();
}
}
F5 ,Shell 就可以RUN 起来啦
3 .创建Hello World 模块
3.1 .在解决方案中添加一个新的项目“HelloWorldModule ”(暂且ClassLibrary 类型吧)
3.2. 添加CAL 库到项目引用中,目前添加Microsoft.Practices.Composite 和Microsoft.Practices.Composite.Wpf 就可以了。
3.3 .从语法层面讲,要实现一个Module ,需要实现IModule 接口,OK ,新建一个HelloWorldModule 类:
public class HelloWorldModule : IModule
{
#region IModule Members
public void Initialize()
{
System.Windows.MessageBox.Show("this is hello module");
}
#endregion
}
我们这里为了避免扰乱读者视线,简化一下,就上该Module 显示一个MessageBox 就OK 了。
4 .将模块加载到Shell Project 中
我们可以看到Shell Project 和HelloWorld Project 是完全独立的两个项目,在实际开发中,它们可能是由两个不同的Team 独立开发和测试的。所以为了能在Shell 中使用HelloWord ,CAL 提供了多种方式来发现和加载模块,最简单的当然是静态加载即直接项目引用,我们这里采用配件文件的形式来实现(CAL 还提供了通过扫描文件夹的方式来加载)
4.1 .添加配置文件
回到Shell Project ,在该项目中添加Application Configuration File ,其会生成一个App.config 文件,在这个文件中我们可以配置系统模块组成结构、加载顺序以及模块之间的依赖性:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="modules" type="Microsoft.Practices.Composite.Modularity.ModulesConfigurationSection, Microsoft.Practices.Composite"/>
</configSections>
<modules>
<module assemblyFile="HelloWorldModule.dll" moduleType="HelloWorldModule.HelloWorldModule" moduleName="HelloWorldModule">
</module>
</modules>
</configuration>
4.2 .指定加载方式
然后回到我们的Bootstrapper 类,指定我们的模块加载方式为配置文件加载:
protected override IModuleEnumerator GetModuleEnumerator()
{
var configStory = new ConfigurationStore();
return new ConfigurationModuleEnumerator(configStory);
}
4.3 .指定模块生成位置
我们知道,模块的默认生成位置是项目的DEBUG (与RELEASE )目录,这会导致一个问题是:我们的Shell 项目不知道这些模块的生成文件位置从而找不到模块文件,所以我们可以通过模块项目的Build Events 中的Post-build event command line 来将生成的文件自动拷贝到Shell 项目的DEBUG (或RELEASE )目录下:
xcopy "$(TargetDir)*.*" "$(SolutionDir)CAG_HelloWorld\bin\$(ConfigurationName)" /Y
(其中CAG_HelloWorld 是Shell 项目的名称)
重新生成一下项目,F5 ,OK
5 .将模块中的View 注入到Shell 中
在上面的示例中,我们仅仅在HelloWord 模块中,显示了一个MessageBox ,现在我们看看如何在其中加入一个View ,并在Shell 中显示出来
5.1 .在Shell 中添加一个Region
回到Shell.xaml ,在其中添加一个容器控件作为一个Region ,你可以将Region 看做是一个占位符,其用于放置我们的View
<Window x:Class="CAG_HelloWorld.Shell"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="https://www.codeplex.com/CompositeWPF"
Title="Shell" Height="300" Width="300">
<Grid>
<ItemsControl cal:RegionManager.RegionName="MainRegion"/>
</Grid>
</Window>
5.2 .在HelloWord Project 中加入HelloWorldView
添加一个UserControl 到HelloWord Project 中(其实也可以是其他UI 元素),在上面任意显示点什么东西,比如一个带有HelloWord 字样的TextBlock 。其将作为我们的View 。
5.3 .将View 注入到Region 中
这项工作是由Module 在模块初始化来完成的。首先我们需要找到指定的View 要注入到Region ,而RegionManager 提供相应的功能:
IRegion mainRegion = regionManager.Regions["MainRegion"];
然后我们可以将我们的View 加到给Region 中并激活它了:
var view = new HelloWorldView();
mainRegion.Add(view);
mainRegion.Activate(view);
总的说来,我们的HelloWorldModule 代码如下所示:
public class HelloWorldModule : IModule
{
private readonly IRegionManager regionManager;
public HelloWorldModule(IRegionManager regionManager)
{
this.regionManager = regionManager;
}
#region IModule Members
public void Initialize()
{
IRegion mainRegion = regionManager.Regions["MainRegion"];
var view = new HelloWorldView();
mainRegion.Add(view);
mainRegion.Activate(view);
}
#endregion
}
OK ,至此,DEMO 打造完毕,当然这step by step 的打造会让人知其然不知其所以然,但问了不混淆视线,就没有引入CAL 的其他特性以及模块内部并没很好地遵循MVP 或MVC 等模式。
下一篇:[Prism]Composite Application Guidance for WPF(4) -- -- Bootstrapper-周银辉