創建第一個Composite WPF Application
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="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:cal="http://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等模式。