Prism for WPF 搭建一个简单的模块化开发框架(一)

最近闲来无事又想搞搞WPF。。。。。
做个框架吧,可能又是半途而废。。。。总是坚持不下来

不废话了,

先看一下工程结构

Prism for WPF 搭建一个简单的模块化开发框架(一)_第1张图片

布局大概是这样的

SystemHeader
Aside Main
Footer

 

PW.SystemHeader是用来放导航条,Log或者系统名称的

PW.Aside是准备放每个模块的树形菜单的,可以根据后续系统的需要做相应的变动和扩展

PW.Login就是一个登陆的模块了

PW.Footer只是一个底部的占位栏,需要的话可以放置一些显示信息

Main初始化时存放了Login的region 此时SystemHeader、Aside、Footer还未加载,所以主界面就算一个登陆页面

在登陆之后LoadModule,对应的区域也就加载上对用的模块了
主窗体布局代码是这样的


    
        
    
    
        
            
            
        
        
            
                
                         
                
            
        
        
               
    	
            
            
            
    	
        
            
            
        
        
            
        
        
            
        
        
            
        
        
                
        
    
    

那么到底是怎么实现模块化松耦合呢,先贴一下代码

Bootstrapper.cs

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.

namespace PW.Desktop
{
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Windows;
    using Prism.Logging;
    using Prism.Modularity;
    using Prism.Mef;

    /// 
    /// Initializes Prism to start this quickstart Prism application to use Managed Extensibility Framework (MEF).
    /// 
    public class Bootstrapper : MefBootstrapper
    {
        private readonly CallbackLogger callbackLogger = new CallbackLogger();

        /// 
        /// Creates the shell or main window of the application.
        /// 
        /// The shell of the application.
        /// 
        /// If the returned instance is a , the
        ///  will attach the default  of
        /// the application in its  attached property
        /// in order to be able to add regions by using the 
        /// attached property from XAML.
        /// 
        protected override DependencyObject CreateShell()
        {
            return this.Container.GetExportedValue();
        }

        /// 
        /// Initializes the shell.
        /// 
        /// 
        /// The base implemention ensures the shell is composed in the container.
        /// 
        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.MainWindow = (Shell) this.Shell;
            Application.Current.MainWindow.Show();
        }

        /// 
        /// Configures the  used by MEF.
        /// 
        /// 
        /// The base implementation does nothing.
        /// 
        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            // Add this assembly to export ModuleTracker
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(Bootstrapper).Assembly));

            // Module A is referenced in in the project and directly in code.
            this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(PW.LogIn.LoginModule).Assembly));

            // Module B and Module D are copied to a directory as part of a post-build step.
            // These modules are not referenced in the project and are discovered by inspecting a directory.
            // Both projects have a post-build step to copy themselves into that directory.
            DirectoryCatalog catalog = new DirectoryCatalog("DirectoryModules");
            this.AggregateCatalog.Catalogs.Add(catalog);
        }

        /// 
        /// Configures the .
        /// May be overwritten in a derived class to add specific type mappings required by the application.
        /// 
        /// 
        /// The base implementation registers all the types direct instantiated by the bootstrapper with the container.
        /// The base implementation also sets the ServiceLocator provider singleton.
        /// 
        protected override void ConfigureContainer()
        {
            base.ConfigureContainer();

            // Because we created the CallbackLogger and it needs to be used immediately, we compose it to satisfy any imports it has.
            this.Container.ComposeExportedValue(this.callbackLogger);
        }

        /// 
        /// Creates the  used by Prism.
        /// 
        /// 
        /// The base implementation returns a new ModuleCatalog.
        /// 
        /// 
        /// A ConfigurationModuleCatalog.
        /// 
        protected override IModuleCatalog CreateModuleCatalog()
        {
            // When using MEF, the existing Prism ModuleCatalog is still the place to configure modules via configuration files.
            return new ConfigurationModuleCatalog();
        }

        /// 
        /// Create the  used by the bootstrapper.
        /// 
        /// 
        /// The base implementation returns a new TextLogger.
        /// 
        /// 
        /// A CallbackLogger.
        /// 
        protected override ILoggerFacade CreateLogger()
        {
            // Because the Shell is displayed after most of the interesting boostrapper work has been performed,
            // this quickstart uses a special logger class to hold on to early log entries and display them 
            // after the UI is visible.
            return this.callbackLogger;
        }
    }
}

这里可以看到,基本上就算copy了Prism的demo代码,只是略微改动了一下ConfigureAggregateCatalog方法

手动加载了LogIn模块,这里工程里需要引入Login模块,然后剩余的所有布局模块以及系统模块都是在DirectoryModules下面
程序生成目录下面是这样的

Prism for WPF 搭建一个简单的模块化开发框架(一)_第2张图片

Prism for WPF 搭建一个简单的模块化开发框架(一)_第3张图片

这样的好处就算,各模块互不相干,以后可以像插件一样做一个新的模块放到DirectoryModules就能运行

然后每个模块下面只要做一个module的接口实现类类似AsideModule.cs这样

using Prism.Modularity;
using Prism.Mef.Modularity;
using Prism.Regions;
using System.ComponentModel.Composition;
using System;
using PW.Infrastructure;

namespace PW.Aside
{
    [ModuleExport(typeof(AsideModule), InitializationMode = InitializationMode.OnDemand)]
    public class AsideModule : IModule
    {
        private readonly IModuleTracker moduleTracker;
        private readonly IRegionManager regionManager;

        /// 
        /// Initializes a new instance of the  class.
        /// 
        /// The module tracker.
        [ImportingConstructor]
        public AsideModule(IModuleTracker moduleTracker, IRegionManager regionManager)
        {
            if (moduleTracker == null)
            {
                throw new ArgumentNullException("moduleTracker");
            }

            this.moduleTracker = moduleTracker;
            this.moduleTracker.RecordModuleConstructed(ModuleNames.Aside);
            this.regionManager = regionManager;
        }


        /// 
        /// Notifies the module that it has be initialized.
        /// 
        public void Initialize()
        {
            this.moduleTracker.RecordModuleInitialized(ModuleNames.Aside);
            regionManager.RegisterViewWithRegion(RegionNames.Aside, typeof(MenuView));
        }
    }
}

每个模块的基本上都一样,只是在Initialize中去为当前Region注册不同的view
好像也没什么好写的了,差不多就这样吧

说一下我遇到的坑和怎么解决的吧

就说布局中的MainRegion,因为初始化拿它加载了login模块,但是在登陆成功后想去加载Map或者SystemSet时,本来想的是用RegionManager更改mainContentControl的Region名称,但是死活不行,各种报错,有一种方法是能做到去加载不同的Region的,就是用ItemsControl,但是用ItemsControl效果很不好,不是全屏显示在MainRegion里

然后查资料,问csdn,都没有结构,可能是现在用wpf的本来就少吧,

最后没事儿时偶然就想到了,在不同的模块能有自己独立的Region做导航,MainRegion只是导航到各模块的主页面,就这样解决了

下面是做到现在的截图

Prism for WPF 搭建一个简单的模块化开发框架(一)_第4张图片

Prism for WPF 搭建一个简单的模块化开发框架(一)_第5张图片

这个本来是打算做一个登陆后的主导航的,上边和左边是要去掉的,还没处理,这时候布局其实已经出来了

Prism for WPF 搭建一个简单的模块化开发框架(一)_第6张图片

再来几个换个风格的,其实就是换个背景图

Prism for WPF 搭建一个简单的模块化开发框架(一)_第7张图片

Prism for WPF 搭建一个简单的模块化开发框架(一)_第8张图片

Prism for WPF 搭建一个简单的模块化开发框架(一)_第9张图片

写的比较乱,想用到项目里,就不上源码了,框架样式都还需要调整,对wpf不熟悉,也是写到哪查到哪,各种不会

现在准备给各模块做公用样式呢,又不知道怎么弄好了,,,,我多想有一个wpf的前辈给指教指教啊。。。。看到的朋友知道怎么弄可以给说一下啊,有好的方法,好的建议都能写下来啊,,,,感觉自己实在是有点瞎弄啊

你可能感兴趣的:(WPF)