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

最近闲来无事又想搞搞WPF。。。。。

做个框架吧,可能又是半途而废。。。。总是坚持不下来

不废话了,

先看一下工程结构

布局大概是这样的

SystemHeader
Aside Main
Footer

 

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

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

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

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

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

在登陆之后LoadModule,对应的区域也就加载上对用的模块了

主窗体布局代码是这样的

<Window x:Class="PW.Desktop.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" mc:Ignorable="d"
xmlns:local="clr-namespace:PW.Desktop"
xmlns:prism="http://www.codeplex.com/prism"
x:Name="Window"
Title="Desktop"
WindowStartupLocation="CenterScreen"
UseLayoutRounding="True"
Width="1024" Height="768" WindowState="Maximized" Loaded="Window_Loaded" WindowStyle="None" ResizeMode="NoResize">
<Window.Background>
<ImageBrush ImageSource="Images/bg/ocean.jpg"/>
</Window.Background>
<Grid x:Name="window">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Height="30" Background="{DynamicResource ModuleControl.Panel.BackgroundBrush}" MouseLeftButtonDown="Grid_MouseLeftButtonDown" Cursor="Hand">
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" FlowDirection="RightToLeft">
<Button Width="25" Height="25" Content="X" x:Name="closeBtn" Click="closeBtn_Click"></Button>
<Button Width="25" Height="25" Content="口" x:Name="maxBtn" Click="maxBtn_Click"></Button>
<Button Width="25" Height="25" Content="-" x:Name="minBtn" Click="minBtn_Click"></Button>
</StackPanel>
</Grid>
<Grid x:Name="LayoutRoot" Grid.Row="1"> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Grid.Column="0" x:Name="gridHeader" Grid.ColumnSpan="2" Margin="0">
<ContentControl x:Name="headerContentControl" prism:RegionManager.RegionName="HeaderRegion" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ContentControl>
</Grid>
<Grid Grid.Row="1" Grid.Column="0" x:Name="gridAside" Margin="0">
<ContentControl x:Name="asideContentControl" prism:RegionManager.RegionName="AsideRegion" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ContentControl>
</Grid>
<Grid Grid.Row="1" Grid.Column="1" x:Name="gridMain" Margin="0">
<ContentControl x:Name="mainContentControl" prism:RegionManager.RegionName="MainRegion" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ContentControl>
</Grid>
<Grid Grid.Row="3" Grid.Column="0" x:Name="gridFooter" Grid.ColumnSpan="2" Margin="0">
<ContentControl x:Name="footerContentControl" prism:RegionManager.RegionName="FooterRegion" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"></ContentControl>
</Grid>
</Grid>
</Grid>
</Window>

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

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; /// <summary>
/// Initializes Prism to start this quickstart Prism application to use Managed Extensibility Framework (MEF).
/// </summary>
public class Bootstrapper : MefBootstrapper
{
private readonly CallbackLogger callbackLogger = new CallbackLogger(); /// <summary>
/// Creates the shell or main window of the application.
/// </summary>
/// <returns>The shell of the application.</returns>
/// <remarks>
/// If the returned instance is a <see cref="DependencyObject"/>, the
/// <see cref="MefBootstrapper"/> will attach the default <seealso cref="Microsoft.Practices.Composite.Regions.IRegionManager"/> of
/// the application in its <see cref="Microsoft.Practices.Composite.Presentation.Regions.RegionManager.RegionManagerProperty"/> attached property
/// in order to be able to add regions by using the <seealso cref=""Microsoft.Practices.Composite.Presentation.Regions.RegionManager.RegionNameProperty"/>
/// attached property from XAML.
/// </remarks>
protected override DependencyObject CreateShell()
{
return this.Container.GetExportedValue<Shell>();
} /// <summary>
/// Initializes the shell.
/// </summary>
/// <remarks>
/// The base implemention ensures the shell is composed in the container.
/// </remarks>
protected override void InitializeShell()
{
base.InitializeShell(); Application.Current.MainWindow = (Shell) this.Shell;
Application.Current.MainWindow.Show();
} /// <summary>
/// Configures the <see cref="AggregateCatalog"/> used by MEF.
/// </summary>
/// <remarks>
/// The base implementation does nothing.
/// </remarks>
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);
} /// <summary>
/// Configures the <see cref="CompositionContainer"/>.
/// May be overwritten in a derived class to add specific type mappings required by the application.
/// </summary>
/// <remarks>
/// The base implementation registers all the types direct instantiated by the bootstrapper with the container.
/// The base implementation also sets the ServiceLocator provider singleton.
/// </remarks>
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<CallbackLogger>(this.callbackLogger);
} /// <summary>
/// Creates the <see cref="IModuleCatalog"/> used by Prism.
/// </summary>
/// <remarks>
/// The base implementation returns a new ModuleCatalog.
/// </remarks>
/// <returns>
/// A ConfigurationModuleCatalog.
/// </returns>
protected override IModuleCatalog CreateModuleCatalog()
{
// When using MEF, the existing Prism ModuleCatalog is still the place to configure modules via configuration files.
return new ConfigurationModuleCatalog();
} /// <summary>
/// Create the <see cref="ILoggerFacade"/> used by the bootstrapper.
/// </summary>
/// <remarks>
/// The base implementation returns a new TextLogger.
/// </remarks>
/// <returns>
/// A CallbackLogger.
/// </returns>
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下面

程序生成目录下面是这样的

这样的好处就算,各模块互不相干,以后可以像插件一样做一个新的模块放到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; /// <summary>
/// Initializes a new instance of the <see cref="ModuleB"/> class.
/// </summary>
/// <param name="moduleTracker">The module tracker.</param>
[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;
} /// <summary>
/// Notifies the module that it has be initialized.
/// </summary>
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只是导航到各模块的主页面,就这样解决了

下面是做到现在的截图

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

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

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

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

Prism for WPF 搭建一个简单的模块化开发框架(一)的更多相关文章

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

    原文:Prism for WPF 搭建一个简单的模块化开发框架 (一个节点) 这里我就只贴图不贴代码了,看看这个节点之前的效果 觉得做的好的地方可以范之前的文章看看 有好的建议也可以说说   填充数据 ...

  2. Prism for WPF 搭建一个简单的模块化开发框架(六)隐藏菜单、导航

    原文:Prism for WPF 搭建一个简单的模块化开发框架(六)隐藏菜单.导航 这个实际上是在聊天之前做的,一起写了,也不分先后了 看一下效果图,上面是模块主导航,左侧是模块内菜单,现在加一下隐藏 ...

  3. Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务、WCF消息头添加安全验证Token

    原文:Prism for WPF 搭建一个简单的模块化开发框架(四)异步调用WCF服务.WCF消息头添加安全验证Token 为什么选择wcf?   因为好像wcf和wpf就是哥俩,,, 为什么选择异步 ...

  4. Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天、消息模块

    原文:Prism for WPF 搭建一个简单的模块化开发框架(五)添加聊天.消息模块 中秋节假期没事继续搞了搞 做了各聊天的模块,需要继续优化 第一步画页面 页面参考https://github.c ...

  5. Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单

    原文:Prism for WPF 搭建一个简单的模块化开发框架(三) 给TreeView加样式做成菜单 昨天晚上把TreeView的样式做了一下,今天给TreeView绑了数据,实现了切换页面功能 上 ...

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

    原文:Prism for WPF 搭建一个简单的模块化开发框架(二) 今天又有时间了,再改改,加了一些控件全局的样式 样式代码 <ResourceDictionary xmlns="h ...

  7. 用express搭建一个简单的博客系统

    转自:https://blog.csdn.net/qq_29721837/article/details/62055603 Express 简介 Express 是一个简洁而灵活的 node.js W ...

  8. 从零开始搭建一个简单的基于webpack的vue开发环境

    原文地址:https://segmentfault.com/a/1190000012789253?utm_source=tag-newest 从零开始搭建一个简单的基于webpack的react开发环 ...

  9. 用nodejs搭建一个简单的服务器

    使用nodejs搭建一个简单的服务器 nodejs优点:性能高(读写文件) 数据操作能力强 官网:www.nodejs.org 验证是否安装成功:cmd命令行中输入node -v 如果显示版本号表示安 ...

随机推荐

  1. 解析纯真IP地址库

    一周以来,一直在做 IP地址库的解析.从调研到编码到优化,大概花了有七八天的时间.感觉很好玩.总结一下整个做的过程. 1.关于IP 地址库的解析方式 目前主要的解析方式有两种:通过API,或通过IP数 ...

  2. BZOJ1879:[SDOI2009]Bill的挑战(状压DP)

    Description Input 本题包含多组数据.  第一行:一个整数T,表示数据的个数.  对于每组数据:  第一行:两个整数,N和K(含义如题目表述).  接下来N行:每行一个字符串. T ≤ ...

  3. Kali-linux应用更新和配置额外安全工具

    本节将介绍更新Kali的过程和配置一些额外的工具.这些工具在后面的章节中将是有用的.Kali软件包不断地更新和发布之间,用户很快发现一套新的工具比最初在DVD ROM上下载的软件包更有用.本节将通过更 ...

  4. ASP.NET Web API编程——使用自签名SSL证书

    1自签名SSL证书的创建 创建自签名SSL工具xca为:https://sourceforge.net/projects/xca/ 创建过程 1)创建根证书 打开软件,界面如下. 点击,看到下拉菜单, ...

  5. npm run build 打包后,如何运行在本地查看效果

    目前,使用vue-cli脚手架写了一个前端项目,之前一直是使用npm run dev 在8080端口上进行本地调试.项目已经进行一半了,今天有时间突然想使用npm run build进行上线打包,试试 ...

  6. CVPR 2016 paper reading (2)

    1. Sketch me that shoe, Qian Yu, Feng Liu, Yi-Zhe Song, Tao Xiang, Timothy M. Hospedales, Cheng Chan ...

  7. centos7 yum安装mysql后启动不起来问题

    [root@localhost ~]# systemctl start mysqld       启动失败 Job for mysqld.service failed because the cont ...

  8. nodejs实战的github地址,喜欢的你还等啥

    第一章.第二章:使用Express + MongoDB搭建多人博客:https://github.com/nswbmw/N-blog 第三章:使用Redis搭建漂流瓶服务器:https://githu ...

  9. Faster Alternatives to glReadPixels and glTexImage2D in OpenGL ES

    In the development of Shou, I’ve been using GLSL with NEON to manipulate image rotation, scaling and ...

  10. Java JVM技术

    .1.     java监控工具使用 .1.1.    jconsole jconsole是一种集成了上面所有命令功能的可视化工具,可以分析jvm的内存使用情况和线程等信息. 启动jconsole 通 ...