Prism_Moudle
因为项目需要,在研究Prism框架。。特地做个小跳转DEMO以备记忆。
Prism相关DLL下载地址:https://files.cnblogs.com/files/82767136/PrismDll.rar
本DEMO,功能很简单,主界面放置3个按钮,通过点击不同的按钮在右侧跳转展现不同的模块而已。
项目通过一个WPF应用程序HelloWord,作为Shell,
3个类库文件,作为模块。
一、新建WPF项目-Shell
Shell界面设计如下:
界面代码XAML:
<Window x:Class="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/prism" xmlns:region="clr-namespace:Prism.Regions;assembly=Prism.Wpf" Title="Hello World" Height="300" Width="400"> <Grid ShowGridLines="True"> <Grid.ColumnDefinitions> <ColumnDefinition Width="150"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <StackPanel > <Button Click="Button_Click" Width="100" Height="25" Margin="5">HelloWord</Button> <Button Click="Button_ClickA" Width="100" Height="25" Margin="5">ModuleA</Button> <Button Click="Button_ClickB" Width="100" Height="25" Margin="5">ModuleB</Button> </StackPanel> <Border Margin="0, 0, 0, 0" BorderThickness="0" Grid.Column="1" > <ContentControl x:Name="mainContent" region:RegionManager.RegionName="MainRegion" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0, 0, 0, 0" BorderThickness="0"> </ContentControl> </Border> </Grid> </Window>
后台代码:
using System.Windows; using System; using System.Windows.Interop; using Prism.Regions; using Microsoft.Practices.ServiceLocation; using Prism.Events; using Prism.Modularity; using A; using B; using HelloWorld.Views; namespace HelloWorld { /// <summary> /// Interaction logic for Shell.xaml /// </summary> public partial class Shell : Window { #region [属性定义] /// <summary> /// 占位符管理器 /// </summary> public IRegionManager _regionManager { get; set; } /// <summary> /// 模块管理器 /// </summary> public IModuleManager _moduleManager { get; set; } #endregion public Shell() { InitializeComponent(); this.Loaded += MainWindow_Loaded; //当前占位符管理器对象 _regionManager = ServiceLocator.Current.GetInstance<IRegionManager>(); //当前模块管理器对象-用于管理模块加载,可以实现动态加载 _moduleManager = ServiceLocator.Current.GetInstance<IModuleManager>(); //IEventAggregator:事件处理接口,采用事件订阅、发布原理 通过IEventAggregator接口获取事件服务: /*Shell界面跳转*/ ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ShellSwitchEvent>().Subscribe(ShellSwitch); //初始化加载 LoadModule(); //初始化加载HelloWord模块 //RequestNavigate:进行页面切换 //初始化加载首界面 _regionManager.RequestNavigate("MainRegion", new Uri(typeof(HelloWorldModule).Name, UriKind.Relative)); } private void ShellSwitch(ShellSwitchParams page) { switch (page) { case ShellSwitchParams.HelloWord: { _regionManager.RequestNavigate("MainRegion", new Uri(typeof(HelloWorldView).Name, UriKind.Relative)); break; } case ShellSwitchParams.ModuleA: { //_regionManager.RequestNavigate(RegionNames.ShellRegion, new Uri(typeof(LoginView).Name, UriKind.Relative)); ServiceLocator.Current.GetInstance<IRegionManager>().RequestNavigate("MainRegion", new Uri(typeof(AView).Name, UriKind.Relative)); break; } case ShellSwitchParams.ModuleB: { ServiceLocator.Current.GetInstance<IRegionManager>().RequestNavigate("MainRegion", new Uri(typeof(BView).Name, UriKind.Relative)); break; } default: { break; } } } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { //获取当前窗体句柄 WindowInteropHelper wndHelper = new WindowInteropHelper(this); //设置当前界面风格 BorderHelper.SetWindowNoBorder(wndHelper.Handle); } // 加载模块 private void LoadModule() { _moduleManager.LoadModule(typeof(HelloWorldModule).Name); _moduleManager.LoadModule(typeof(AModule).Name); _moduleManager.LoadModule(typeof(BModule).Name); } private void Button_Click(object sender, RoutedEventArgs e) { ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ShellSwitchEvent>().Publish(ShellSwitchParams.HelloWord); } private void Button_ClickA(object sender, RoutedEventArgs e) { ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ShellSwitchEvent>().Publish(ShellSwitchParams.ModuleA); } private void Button_ClickB(object sender, RoutedEventArgs e) { ServiceLocator.Current.GetInstance<IEventAggregator>().GetEvent<ShellSwitchEvent>().Publish(ShellSwitchParams.ModuleB); } } }
App.xaml 删除默认的启动方式,后台重写启动代码
<Application x:Class="HelloWorld.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Application.Resources> </Application.Resources> </Application>
using System.Windows; namespace HelloWorld { /// <summary> /// Interaction logic for App.xaml /// </summary> public partial class App : Application { //重写启动方法 protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); Bootstrapper bootstrapper = new Bootstrapper(); bootstrapper.Run(); } } }
其中启动精灵Bootstrapper
using System.Windows; using Microsoft.Practices.ServiceLocation; using System; using System.Collections.ObjectModel; using Prism.Modularity; using Prism.Unity; using A; using B; namespace HelloWorld { /// <summary> /// 自定义的启动控制类,继承Prism框架 /// UnityBootstrapper:代表底层是通过Unity作为IOC容器 /// </summary> class Bootstrapper : UnityBootstrapper { //重写创建Shell壳对象 protected override DependencyObject CreateShell() { return (Shell)this.Container.Resolve(typeof(Shell), "Shell"); } //protected override DependencyObject CreateShell() //{ // //创建主界面UnityContainer // return this.Container.Resolve<Shell>(); // //return ServiceLocator.Current.GetInstance<Shell>(); // //return (Shell)this.Container.Resolve(typeof(Shell), "Shell"); //} //重写初始化Shell protected override void InitializeShell() { base.InitializeShell(); //// SILVERLIGHT //App.Current.RootVisual = (UIElement)this.Shell; //App.Current.MainWindow = (Window)this.Shell; //App.Current.MainWindow.Show(); //显示主界面 App.Current.MainWindow = (Window)this.Shell; App.Current.MainWindow.Show(); /************************* * Module中的初始化方法Initialize,将Region占位符替换为具体的界面 * 如果发现Shell中的出现的Region对应的占位符,就用Module中设置的字典映射,动态匹配, * 找到Region对应的界面,替换Shell中的指定位置。 ******************* ****/ } //重写模块创建方法 protected override IModuleCatalog CreateModuleCatalog() { return new ModuleCatalog(); } //重写配置应用模块 protected override void ConfigureModuleCatalog() { this.ModuleCatalog.AddModule(new ModuleInfo() { ModuleName = typeof(HelloWorldModule).Name, ModuleType = typeof(HelloWorldModule).AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand }); this.ModuleCatalog.AddModule(new ModuleInfo() { ModuleName = typeof(AModule).Name, ModuleType = typeof(AModule).AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand //动态加载 }); this.ModuleCatalog.AddModule(new ModuleInfo() { ModuleName = typeof(BModule).Name, ModuleType = typeof(BModule).AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand }); } //重写容器配置 protected override void ConfigureContainer() { base.ConfigureContainer(); } } }
跳转参数:ShellSwitchEvent
using Prism.Events; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HelloWorld {/// <summary> /// Shell界面跳转 /// </summary> public class ShellSwitchEvent : PubSubEvent<ShellSwitchParams> { } /// <summary> /// 跳转参数 /// </summary> public enum ShellSwitchParams { /// <summary> /// HelloWord模块 /// </summary> HelloWord = 1, /// <summary> /// A模块 /// </summary> ModuleA = 2, /// <summary> /// B模块 /// </summary> ModuleB = 3, } }
窗体样式:
BorderHelper
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HelloWorld { /// <summary> /// 设置窗体边框样式。 /// WPF 中的用法: /// WindowInteropHelper wndHelper = new WindowInteropHelper(this); /// BorderHelper.SetWindowNoBorder(wndHelper.Handle); /// </summary> public class BorderHelper { /// <summary> /// 带有外边框和标题的windows的样式 /// </summary> public const long WS_CAPTION = 0x00C00000L; public const long WS_CAPTION_2 = 0X00C0000L; // public const long WS_BORDER = 0X0080000L; /// <summary> /// window 扩展样式 分层显示 /// </summary> public const long WS_EX_LAYERED = 0x00080000L; public const long WS_CHILD = 0x40000000L; /// <summary> /// 带有alpha的样式 /// </summary> public const long LWA_ALPHA = 0x00000002L; /// <summary> /// 颜色设置 /// </summary> public const long LWA_COLORKEY = 0x00000001L; /// <summary> /// window的基本样式 /// </summary> public const int GWL_STYLE = -16; /// <summary> /// window的扩展样式 /// </summary> public const int GWL_EXSTYLE = -20; /// <summary> /// 设置窗体的样式 /// </summary> /// <param name="handle">操作窗体的句柄</param> /// <param name="oldStyle">进行设置窗体的样式类型.</param> /// <param name="newStyle">新样式</param> [System.Runtime.InteropServices.DllImport("User32.dll")] //[DllImport("User32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] // public static extern void SetWindowLong(IntPtr handle, int oldStyle, long newStyle); public static extern void SetWindowLong(IntPtr handle, int oldStyle, IntPtr newStyle); /// <summary> /// 获取窗体指定的样式. /// </summary> /// <param name="handle">操作窗体的句柄</param> /// <param name="style">要进行返回的样式</param> /// <returns>当前window的样式</returns> [System.Runtime.InteropServices.DllImport("User32.dll")] // [DllImport("User32.dll", EntryPoint = "GetWindowLong",CallingConvention = CallingConvention.Cdecl)] public static extern long GetWindowLong(IntPtr handle, int style); /// <summary> /// 设置窗体的工作区域. /// </summary> /// <param name="handle">操作窗体的句柄.</param> /// <param name="handleRegion">操作窗体区域的句柄.</param> /// <param name="regraw">if set to <c>true</c> [regraw].</param> /// <returns>返回值</returns> [System.Runtime.InteropServices.DllImport("User32.dll")] public static extern int SetWindowRgn(IntPtr handle, IntPtr handleRegion, bool regraw); /// <summary> /// 创建带有圆角的区域. /// </summary> /// <param name="x1">左上角坐标的X值.</param> /// <param name="y1">左上角坐标的Y值.</param> /// <param name="x2">右下角坐标的X值.</param> /// <param name="y2">右下角坐标的Y值.</param> /// <param name="width">圆角椭圆的width.</param> /// <param name="height">圆角椭圆的height.</param> /// <returns>hRgn的句柄</returns> [System.Runtime.InteropServices.DllImport("gdi32.dll")] public static extern IntPtr CreateRoundRectRgn(int x1, int y1, int x2, int y2, int width, int height); /// <summary> /// Sets the layered window attributes. /// </summary> /// <param name="handle">要进行操作的窗口句柄</param> /// <param name="colorKey">RGB的值</param> /// <param name="alpha">Alpha的值,透明度</param> /// <param name="flags">附带参数</param> /// <returns>true or false</returns> [System.Runtime.InteropServices.DllImport("User32.dll")] public static extern bool SetLayeredWindowAttributes(IntPtr handle, ulong colorKey, byte alpha, long flags); //================================================================================= /// <summary> /// 设置窗体为无边框风格 /// </summary> /// <param name="hWnd"></param> public static void SetWindowNoBorder(IntPtr hWnd) { int oldstyle = (int)BorderHelper.GetWindowLong(hWnd, BorderHelper.GWL_STYLE); oldstyle &= (int)(~(WS_CAPTION | WS_CAPTION_2)); SetWindowLong(hWnd, GWL_STYLE, (IntPtr)oldstyle); } //public enum GetWindowLongFields //{ // // ... // GWL_EXSTYLE = (-20), // // ... //} //[Flags] //public enum ExtendedWindowStyles //{ // // ... // WS_EX_TOOLWINDOW = 0x00000080, // // ... //} } }
这样整个主界面Shell就搭建完毕了。
接下来就是模块的编写方式,就拿模块A代码举例。
新建类库A,建立WPF用户控件A,以及AModule类文件。
AModule文件:
using Prism.Modularity; using Prism.Regions; namespace A { public class AModule : IModule { private IRegionManager _regionManager; public AModule(IRegionManager regionManager) { this._regionManager = regionManager; } //初始化方法 public void Initialize() { this._regionManager.RegisterViewWithRegion("MainRegion", typeof(AView)); } } }
AView用户控件只是简单的一个文本显示而已。
<UserControl x:Class="A.AView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" > <Grid> <TextBlock Text="ModuleA" Foreground="Green" HorizontalAlignment="Center" VerticalAlignment="Center" FontFamily="Calibri" FontSize="24" FontWeight="Bold"></TextBlock> </Grid> </UserControl>
后台无代码。
这样模块A就实现了接口模块了。
依次实现模块B和HelloWord模块即可。