WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

  • WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)已关闭评论
  • 203 次浏览
  • A+
所属分类:.NET技术
摘要

最近通过WPF开发项目,为了对WPF知识点进行总结,所以利用业余时间,开发一个学生信息管理系统【Student Information Management System】。本文主要简述如何通过WPF+Prism+MAH+WebApi进行开发基于三层架构的桌面版应用程序,仅供学习分享使用,如有不足之处,还请指正。

最近通过WPF开发项目,为了对WPF知识点进行总结,所以利用业余时间,开发一个学生信息管理系统【Student Information Management System】。本文主要简述如何通过WPF+Prism+MAH+WebApi进行开发基于三层架构的桌面版应用程序,仅供学习分享使用,如有不足之处,还请指正。

涉及知识点

  • WPF:WPF(Windows Presentation Foundation)是(微软推出的)基于Windows的用户界面框架,提供了统一的编程模型,语言和框架,做到了分离界面设计人员与开发人员的工作;WPF提供了全新的多媒体交互用户图形界面。相比于WinForm传统开发,在WPF中,通过核心的MVVM设计思想,实现前后端的分离。
  • Prism:Prism是一个用于在 WPF、Xamarin Form、Uno 平台和 WinUI 中构建松散耦合、可维护和可测试的 XAML 应用程序框架。通过Prism,可以简化原生MVVM实现方式,并引入分模块设计思想。在Prism中,每一个功能,都可以设计成一个独立的模块,各个模块之间松耦合,可维护,可测试。框架中包括 MVVM、依赖注入、Command、Message Event、导航、弹窗等功能。在后续程序功能设计中,都会用到。
  • MAH:MahApps是一套基于WPF的界面组件,通过该组件,可以使用较小的开发成本实现一个相对很好的界面效果。作为后端开发,最头疼的就是如何设计美化页面,MAH可以让开发人员用最少的时间来开发Metro风格的页面。
  • WebApi:一般是指ASP.NET WebApi 用于快速开发基于REST风格的数据接口的框架。

Prism的模块化思想

在应用程序开发中,如果不采用模块化思想,那么各个页面混合在一起,看起杂乱无章,具体如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 

当我们引入模块化思想,那么各个模块的界限将变得清晰,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 

 

在本文示例的学生信息管理系统中,就是采用模块思想,使项目的各个模块即相对完整,又相互独立。如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

在开发中,引入模块化思想,通过Prism进行代码布局,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 

 

MVVM思想

MVVM是Model-View-ViewModel(模型-视图-视图模型)的缩写形式,它通常被用于WPF或Silverlight开发。MVVM的根本思想就是界面和业务功能进行分离,View的职责就是负责如何显示数据及发送命令,ViewModel的功能就是如何提供数据和执行命令。各司其职,互不影响。我们可以通过下图来直观的理解MVVM模式:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 

 

在本示例中,所有开发都将遵循MVVM思想的设计模式进行开发,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

页面布局

在学生信息管理系统主界面,根据传统的布局方式,主要分为上(Header),中【左(Navigation),右(Main Content)】,下(Footer)四个部分,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 

 

创建一个模块

一个模块是一个独立的WPF类库,在项目中,一个普通的类实现了IModule接口,就表示一个模块,以学生模块为例,如下所示:

 1 using Prism.Ioc;  2 using Prism.Modularity;  3 using SIMS.StudentModule.ViewModels;  4 using SIMS.StudentModule.Views;  5 using System;  6   7 namespace SIMS.StudentModule  8 {  9     public class StudentModule : IModule 10     { 11         public void OnInitialized(IContainerProvider containerProvider) 12         { 13              14         } 15  16         public void RegisterTypes(IContainerRegistry containerRegistry) 17         { 18             containerRegistry.RegisterForNavigation<Student, StudentViewModel>(nameof(Student)); 19         } 20     } 21 }

注意:在模块中,需要实现两个接口方法。在此模块中的RegisterTypes方法中,可以注册导航,窗口等以及初始化工作。

如果不注册为导航,而是需要注册到某一个Region中,则可以在OnInitialized方法中进行,以导航模块为例,如下所示:

 1 using Prism.Ioc;  2 using Prism.Modularity;  3 using Prism.Regions;  4 using SIMS.NavigationModule.Views;  5 using System;  6   7 namespace SIMS.NavigationModule  8 {  9     public class NavigationModule : IModule 10     { 11         public void OnInitialized(IContainerProvider containerProvider) 12         { 13             var regionManager = containerProvider.Resolve<IRegionManager>(); 14             regionManager.RegisterViewWithRegion("NavRegion",typeof(Navigation)); 15         } 16  17         public void RegisterTypes(IContainerRegistry containerRegistry) 18         { 19         } 20     } 21 }

View和ViewModel自动适配

View和ViewMode在注册导航时,可以手动匹配,也可以自动匹配【需要以固定的方式命名才可以自动适配】。自动适配,需要是在UserControl中,增加一句prism:ViewModelLocator.AutoWireViewModel="True"即可,以标题头为例,如下所示:

 1 <UserControl x:Class="SIMS.Views.Header"  2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   6              xmlns:local="clr-namespace:SIMS.Views"  7              mc:Ignorable="d"  8              xmlns:prism="http://prismlibrary.com/"  9              prism:ViewModelLocator.AutoWireViewModel="True" 10              xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls" 11              d:DesignHeight="100" d:DesignWidth="800"> 12     <UserControl.Resources> 13         <ResourceDictionary> 14             <ResourceDictionary.MergedDictionaries> 15                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> 16             </ResourceDictionary.MergedDictionaries> 17         </ResourceDictionary> 18     </UserControl.Resources> 19  20     <Grid Background="{DynamicResource MahApps.Brushes.Accent}"> 21         <Grid.RowDefinitions> 22             <RowDefinition Height="*"></RowDefinition> 23             <RowDefinition Height="Auto"></RowDefinition> 24         </Grid.RowDefinitions> 25         <TextBlock Grid.Row="0" Text="学生信息管理系统" Foreground="White" FontSize="32" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Center"  Margin="20,5"></TextBlock> 26         <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal"> 27             <TextBlock Text="Hello" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3"></TextBlock> 28             <TextBlock Text="Admin" Foreground="White"  Margin="3" FontWeight="Bold"></TextBlock> 29             <TextBlock Text="|" Foreground="White"  Margin="3"></TextBlock> 30             <TextBlock Text="Logout" Foreground="White"  Margin="3" FontWeight="Bold"></TextBlock> 31         </StackPanel> 32     </Grid> 33  34 </UserControl>

弹出模态窗口

在Prism中,模块中的视图都是以UserControl的形式存在,那么如果需要弹出窗体页面,就需要在ViewModel中,实现IDialogAware接口,以Login登录窗口为例,如下所示:

  1 using Prism.Regions;   2 using Prism.Services.Dialogs;   3 using SIMS.Views;   4 using System;   5 using System.Collections.Generic;   6 using System.Linq;   7 using System.Text;   8 using System.Threading.Tasks;   9 using System.Windows;  10   11 namespace SIMS.ViewModels  12 {  13     public class LoginViewModel : BindableBase, IDialogAware  14     {  15         private IRegionManager _regionManager;  16         private IContainerExtension _container;  17   18         private string userName;  19   20         public string UserName  21         {  22             get { return userName; }  23             set {SetProperty(ref userName , value); }  24         }  25   26         private string password;  27   28         public string Password  29         {  30             get { return password; }  31             set { SetProperty(ref  password , value); }  32         }  33   34   35         public LoginViewModel(IContainerExtension container,IRegionManager regionManager)  36         {  37             this._container = container;  38             this._regionManager = regionManager;  39         }  40   41         private void InitInfo() {  42             var footer = _container.Resolve<Footer>();  43             IRegion footerRegion = _regionManager.Regions["LoginFooterRegion"];  44             footerRegion.Add(footer);  45         }  46   47         #region 命令  48   49         private DelegateCommand loadedCommand;  50   51         public DelegateCommand LoadedCommand  52         {  53             get  54             {  55                 if (loadedCommand == null)  56                 {  57                     loadedCommand = new DelegateCommand(Loaded);  58                 }  59                 return loadedCommand;  60             }  61         }  62   63         private void Loaded()  64         {  65             //InitInfo();  66         }  67   68         private DelegateCommand loginCommand;  69   70         public DelegateCommand LoginCommand  71         {  72             get  73             {  74                 if (loginCommand == null)  75                 {  76                     loginCommand = new DelegateCommand(Login);  77                 }  78                 return loginCommand;  79             }  80         }  81   82         private void Login() {  83             if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(Password)) {  84                 MessageBox.Show("用户名或密码为空,请确认");  85                 return;  86             }  87             if (UserName == "admin" && Password == "abc123")  88             {  89                 CloseWindow();  90             }  91             else {  92                 MessageBox.Show("用户名密码不正确,请确认");  93                 return;  94             }  95         }  96   97         private DelegateCommand cancelCommand;  98   99         public DelegateCommand CancelCommand 100         { 101             get 102             { 103                 if (cancelCommand == null) 104                 { 105                     cancelCommand = new DelegateCommand(Cancel); 106                 } 107                 return cancelCommand; 108             } 109         } 110  111         private void Cancel() { 112             RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)); 113         } 114  115         #endregion 116  117         #region DialogAware接口 118  119         public string Title => "SIMS-Login"; 120  121         public event Action<IDialogResult> RequestClose; 122  123         /// <summary> 124         /// 成功时关闭窗口 125         /// </summary> 126         public void CloseWindow() { 127             RequestClose?.Invoke(new DialogResult(ButtonResult.OK)); 128         } 129  130         public bool CanCloseDialog() 131         { 132             return true; 133         } 134  135         public void OnDialogClosed() 136         { 137             //当关闭时 138             RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)); 139         } 140  141         public void OnDialogOpened(IDialogParameters parameters) 142         { 143             //传递解析参数 144         } 145  146         #endregion 147     } 148 }

实现了IDialogAware接口,表示以窗口的形态出现,在需要弹出窗口的地方进行调用即可。如下所示:

1 public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) {  2     this._container = container; 3     this._regionManager = regionManager; 4     this.eventAggregator = eventAggregator; 5     this._dialogService = dialogService; 6     //弹出登录窗口 7     this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow"); 8     this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation); 9 }

注意:MetroDialogWindow是自定义个一个Metro风格的窗口,如果为空,则采用默认窗口风格。

模块间交互

按照模块化设计思想,虽然各个模块之间相互独立,但是难免为遇到模块之间进行交互的情况,所以Prism提供了事件聚合器,通过命令的发布和订阅来实现模块间的数据交互。以导航模块为例,当点击某一个导航时,发布一个命令,在主窗口订阅此事件,当收到事件时,将此导航对应的页面渲染到主页面区域中。步骤如下:

1. 定义一个事件

 1 using Prism.Events;  2 using System;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7   8 namespace SIMS.Utils.Events  9 { 10     /// <summary> 11     /// 导航事件 12     /// </summary> 13     public class NavEvent : PubSubEvent<string> 14     { 15     } 16 }

2. 发布事件

用户点击导航菜单时,触发NavCommand,然后发布命令。

 1 private DelegateCommand<object> navCommand;  2   3 public DelegateCommand<object> NavCommand  4 {  5     get  6     {  7         if (navCommand == null)  8         {  9  10             navCommand = new DelegateCommand<object>(Navigation); 11         } 12         return navCommand; 13     } 14 } 15  16 private void Navigation(object obj) { 17     var menuItem = (HamburgerMenuItem)obj; 18     if (menuItem != null) {  19         var tag = menuItem.Tag; 20         if (tag!=null) {  21             this.eventAggregator.GetEvent<NavEvent>().Publish(tag.ToString()); 22         } 23     } 24 }

3. 订阅命令

在主窗口,订阅命令,当收到命令时,再初始化模块信息,如下所示:

 1 namespace SIMS.ViewModels  2 {  3     public class MainWindowViewModel:BindableBase  4     {  5   6         private IEventAggregator eventAggregator;  7         private IContainerExtension _container;  8         private IRegionManager _regionManager;  9         private IDialogService _dialogService; 10         public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) {  11             this._container = container; 12             this._regionManager = regionManager; 13             this.eventAggregator = eventAggregator; 14             this._dialogService = dialogService; 15             //弹出登录窗口 16             this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow"); 17             this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation); 18         } 19  20         private void LoginCallback(IDialogResult dialogResult) { 21             if (dialogResult.Result != ButtonResult.OK) { 22                 Application.Current.Shutdown(); 23             } 24         } 25  26         #region 事件和命令 27  28         private DelegateCommand loadedCommand; 29  30         public DelegateCommand LoadedCommand 31         { 32             get { 33                 if (loadedCommand == null) { 34                     loadedCommand = new DelegateCommand(Loaded); 35                 } 36                 return loadedCommand; } 37         } 38  39         private void Loaded() { 40             InitInfo(); 41         } 42  43  44          45  46         private void InitInfo() { 47             var header = _container.Resolve<Header>(); 48             IRegion headerRegion = _regionManager.Regions["HeaderRegion"]; 49             headerRegion.Add(header); 50             // 51             var footer = _container.Resolve<Footer>(); 52             IRegion footerRegion = _regionManager.Regions["FooterRegion"]; 53             footerRegion.Add(footer); 54  55             var welcome = _container.Resolve<Welcome>(); 56             IRegion welcomeRegion = _regionManager.Regions["ContentRegion"]; 57             welcomeRegion.Add(welcome); 58         } 59  60         private void Navigation(string source) { 61             _regionManager.RequestNavigate("ContentRegion", source); 62             //MessageBox.Show(source); 63         } 64  65         #endregion 66     } 67 }

注意:一般情况下,只有在不同模块时,才使用事件聚合器进行事件的订阅和发布。如果是同一模块,则没有必要。

核心代码

模块的配置

各个模块之间相互独立,所以在主模块中进行加载时,需要先进行配置。模块加载的方式有很多种,本例采用App.config配置方式,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 <?xml version="1.0" encoding="utf-8" ?>  2 <configuration>  3     <configSections>  4         <section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf" />  5     </configSections>  6     <startup>  7     </startup>  8     <modules>  9         <module assemblyFile="SIMS.NavigationModule.dll" moduleType="SIMS.NavigationModule.NavigationModule, SIMS.NavigationModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="NavigationModule" startupLoaded="True" /> 10         <module assemblyFile="SIMS.ScoreModule.dll" moduleType="SIMS.ScoreModule.ScoreModule, SIMS.ScoreModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ScoreModule" startupLoaded="True" /> 11         <module assemblyFile="SIMS.StudentModule.dll" moduleType="SIMS.StudentModule.StudentModule, SIMS.StudentModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="StudentModule" startupLoaded="True" /> 12         <module assemblyFile="SIMS.ClassesModule.dll" moduleType="SIMS.ClassesModule.ClassesModule, SIMS.ClassesModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ClassesModule" startupLoaded="True" /> 13         <module assemblyFile="SIMS.CourseModule.dll" moduleType="SIMS.CourseModule.CourseModule, SIMS.CourseModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="CourseModule" startupLoaded="True" /> 14         <module assemblyFile="SIMS.SysManagementModule.dll" moduleType="SIMS.SysManagementModule.SysManagementModule, SIMS.SysManagementModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="SysManagementModule" startupLoaded="True" /> 15     </modules> 16 </configuration>

View Code

启动入口App.xaml,可以用来配置资源字典等初始化操作,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 <prism:PrismApplication x:Class="SIMS.App"  2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  4              xmlns:local="clr-namespace:SIMS"  5              xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"  6              xmlns:prism="http://prismlibrary.com/"  7              >  8     <Application.Resources>  9         <ResourceDictionary> 10             <ResourceDictionary.MergedDictionaries> 11                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> 12                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" /> 13                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> 14                 <ResourceDictionary Source="/Icons/Icons.xaml"></ResourceDictionary> 15             </ResourceDictionary.MergedDictionaries> 16         </ResourceDictionary> 17     </Application.Resources> 18 </prism:PrismApplication>

View Code

启动入口App.xaml.cs,应用程序需要继承PrismApplication基类,才是一个Prism应用程序。在此文件中初始化App.config中配置的模块。如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 namespace SIMS  2 {  3     /// <summary>  4     /// Interaction logic for App.xaml  5     /// </summary>  6     public partial class App : PrismApplication  7     {  8         protected override Window CreateShell()  9         { 10             return Container.Resolve<MainWindow>(); 11         } 12  13         protected override void RegisterTypes(IContainerRegistry containerRegistry) 14         { 15             containerRegistry.RegisterDialog<Login, LoginViewModel>(nameof(Login)); 16             containerRegistry.Register<IDialogWindow, MetroDialogWindow>("MetroDialogWindow"); 17         } 18  19         protected override IModuleCatalog CreateModuleCatalog() 20         { 21             return new ConfigurationModuleCatalog(); 22         } 23     } 24 }

View Code

主窗口MainWindow.xaml页面布局,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 <mahApps:MetroWindow x:Class="SIMS.Views.MainWindow"  2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  6         xmlns:local="clr-namespace:SIMS"  7         mc:Ignorable="d"  8         xmlns:prism="http://prismlibrary.com/"  9         xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls" 10         xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 11         prism:ViewModelLocator.AutoWireViewModel="True" 12         mahApps:Title="SIMS--Student Information Management System" 13         mahApps:TitleCharacterCasing="Normal" 14         d:DesignHeight="1080" d:DesignWidth="1920"             15          WindowState="Maximized"> 16     <Window.Resources> 17         <ResourceDictionary> 18             <ResourceDictionary.MergedDictionaries> 19                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> 20             </ResourceDictionary.MergedDictionaries> 21         </ResourceDictionary> 22     </Window.Resources> 23  24     <i:Interaction.Triggers> 25         <i:EventTrigger EventName="Loaded"> 26             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction> 27         </i:EventTrigger> 28     </i:Interaction.Triggers> 29     <Grid ShowGridLines="True"> 30         <Grid.RowDefinitions> 31             <RowDefinition Height="Auto"></RowDefinition> 32             <RowDefinition Height="*"></RowDefinition> 33             <RowDefinition Height="Auto"></RowDefinition> 34         </Grid.RowDefinitions> 35         <Grid.ColumnDefinitions> 36             <ColumnDefinition Width="Auto"></ColumnDefinition> 37             <ColumnDefinition Width="*"></ColumnDefinition> 38         </Grid.ColumnDefinitions> 39         <ContentControl prism:RegionManager.RegionName="HeaderRegion"  Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" MinHeight="80"></ContentControl> 40         <ContentControl prism:RegionManager.RegionName="NavRegion" Grid.Row="1" Grid.Column="0"></ContentControl> 41         <ContentControl prism:RegionManager.RegionName="ContentRegion" Grid.Row="1" Grid.Column="1"></ContentControl> 42         <ContentControl prism:RegionManager.RegionName="FooterRegion" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" MinHeight="50"></ContentControl> 43     </Grid> 44 </mahApps:MetroWindow>

View Code

主窗口MainWindowViewModel,代码如下:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 namespace SIMS.ViewModels  2 {  3     public class MainWindowViewModel:BindableBase  4     {  5   6         private IEventAggregator eventAggregator;  7         private IContainerExtension _container;  8         private IRegionManager _regionManager;  9         private IDialogService _dialogService; 10         public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) {  11             this._container = container; 12             this._regionManager = regionManager; 13             this.eventAggregator = eventAggregator; 14             this._dialogService = dialogService; 15             //弹出登录窗口 16             this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow"); 17             this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation); 18         } 19  20         private void LoginCallback(IDialogResult dialogResult) { 21             if (dialogResult.Result != ButtonResult.OK) { 22                 Application.Current.Shutdown(); 23             } 24         } 25  26         #region 事件和命令 27  28         private DelegateCommand loadedCommand; 29  30         public DelegateCommand LoadedCommand 31         { 32             get { 33                 if (loadedCommand == null) { 34                     loadedCommand = new DelegateCommand(Loaded); 35                 } 36                 return loadedCommand; } 37         } 38  39         private void Loaded() { 40             InitInfo(); 41         } 42  43  44          45  46         private void InitInfo() { 47             var header = _container.Resolve<Header>(); 48             IRegion headerRegion = _regionManager.Regions["HeaderRegion"]; 49             headerRegion.Add(header); 50             // 51             var footer = _container.Resolve<Footer>(); 52             IRegion footerRegion = _regionManager.Regions["FooterRegion"]; 53             footerRegion.Add(footer); 54  55             var welcome = _container.Resolve<Welcome>(); 56             IRegion welcomeRegion = _regionManager.Regions["ContentRegion"]; 57             welcomeRegion.Add(welcome); 58         } 59  60         private void Navigation(string source) { 61             _regionManager.RequestNavigate("ContentRegion", source); 62             //MessageBox.Show(source); 63         } 64  65         #endregion 66     } 67 }

View Code

导航页面Navigation.xaml页面采用MAH的Hamburger菜单,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

  1 <UserControl x:Class="SIMS.NavigationModule.Views.Navigation"   2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   4              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   5              xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"   6              xmlns:local="clr-namespace:SIMS.NavigationModule.Views"   7              xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"   8              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   9              xmlns:i="http://schemas.microsoft.com/xaml/behaviors"  10              xmlns:prism="http://prismlibrary.com/"  11              prism:ViewModelLocator.AutoWireViewModel="True"  12              d:DesignHeight="300"  13              d:DesignWidth="240"  14              mc:Ignorable="d">  15   16     <UserControl.Resources>  17         <ResourceDictionary>  18             <ResourceDictionary.MergedDictionaries>  19                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />  20                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />  21                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />  22             </ResourceDictionary.MergedDictionaries>  23             <!--  This is the template for all menu items. In this sample we use the glyph items.  -->  24             <DataTemplate x:Key="HamburgerMenuItem" DataType="{x:Type mah:HamburgerMenuGlyphItem}">  25                 <DockPanel Height="48" LastChildFill="True">  26                     <Grid x:Name="IconPart"  27                           DockPanel.Dock="Left">  28   29                         <Image Margin="12"  30                                HorizontalAlignment="Center"  31                                VerticalAlignment="Center"  32                                Source="{Binding Glyph}" />  33                     </Grid>  34                     <TextBlock x:Name="TextPart"  35                                VerticalAlignment="Center"  36                                FontSize="16"  37                                Text="{Binding Label}" />  38                 </DockPanel>  39             </DataTemplate>  40   41   42             <DataTemplate x:Key="HamburgerOptionsMenuItem" DataType="{x:Type mah:HamburgerMenuIconItem}">  43                 <DockPanel Height="48" LastChildFill="True">  44                     <ContentControl x:Name="IconPart"  45                                     Content="{Binding Icon}"  46                                     DockPanel.Dock="Left"  47                                     Focusable="False"  48                                     IsTabStop="False" />  49                     <TextBlock x:Name="TextPart"  50                                VerticalAlignment="Center"  51                                FontSize="16"  52                                Text="{Binding Label}" />  53                 </DockPanel>  54             </DataTemplate>  55         </ResourceDictionary>  56     </UserControl.Resources>  57   58     <Grid Background="{DynamicResource MahApps.Brushes.Accent}">  59         <Grid.ColumnDefinitions>  60             <ColumnDefinition Width="Auto" />  61         </Grid.ColumnDefinitions>  62         <mah:HamburgerMenu x:Name="HamburgerMenuControl" Grid.Column="0"  63                                DisplayMode="CompactOverlay"  64                                Margin="0"  65                                IsPaneOpen="True"  66                              67                                HamburgerButtonHelpText="Please click me"  68                                HamburgerButtonClick="HamburgerMenuControl_HamburgerButtonClick"  69                                ItemTemplate="{StaticResource HamburgerMenuItem}"  70                                OptionsItemTemplate="{StaticResource HamburgerOptionsMenuItem}"  71                                ItemsSource="{Binding NavItems}"  72                                VerticalScrollBarOnLeftSide="False">  73             <i:Interaction.Triggers>  74                 <i:EventTrigger EventName="ItemInvoked">  75                     <i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="{Binding ElementName=HamburgerMenuControl, Path=SelectedItem}" ></i:InvokeCommandAction>  76                 </i:EventTrigger>  77             </i:Interaction.Triggers>  78             <!--  Header  -->  79             <mah:HamburgerMenu.HamburgerMenuHeaderTemplate>  80                 <DataTemplate>  81                     <TextBlock HorizontalAlignment="Center"  82                                    VerticalAlignment="Center"  83                                    FontSize="16"  84                                    Foreground="White"  85                                    Text="" />  86                 </DataTemplate>  87             </mah:HamburgerMenu.HamburgerMenuHeaderTemplate>  88             <mah:HamburgerMenu.OptionsItemsSource>  89                 <mah:HamburgerMenuItemCollection>  90   91                     <mah:HamburgerMenuIconItem x:Name="AboutOption"  92                                                      93                                                    Label="About">  94                         <mah:HamburgerMenuIconItem.Icon>  95                             <iconPacks:PackIconMaterial Width="22"  96                                                             Height="22"  97                                                             HorizontalAlignment="Center"  98                                                             VerticalAlignment="Center"  99                                                             Kind="Help" /> 100                         </mah:HamburgerMenuIconItem.Icon> 101                         <mah:HamburgerMenuIconItem.Tag> 102                             <TextBlock HorizontalAlignment="Center" 103                                            VerticalAlignment="Center" 104                                            FontSize="28" 105                                            FontWeight="Bold"> 106                                     About 107                             </TextBlock> 108                         </mah:HamburgerMenuIconItem.Tag> 109                     </mah:HamburgerMenuIconItem> 110  111                 </mah:HamburgerMenuItemCollection> 112             </mah:HamburgerMenu.OptionsItemsSource> 113             <!--  Content  --> 114             <mah:HamburgerMenu.ContentTemplate> 115                 <DataTemplate> 116                     <Grid x:Name="ContentGrid"> 117                         <Grid.RowDefinitions> 118                             <RowDefinition Height="48" /> 119                             <RowDefinition /> 120                         </Grid.RowDefinitions> 121                         <Border Grid.Row="0" 122                                     Margin="-1 0 -1 0" 123                                     Background="#7A7A7A"> 124                             <TextBlock x:Name="Header" 125                                            HorizontalAlignment="Center" 126                                            VerticalAlignment="Center" 127                                            FontSize="24" 128                                            Foreground="White" 129                                            Text="{Binding Label}" /> 130                         </Border> 131                         <mah:TransitioningContentControl Grid.Row="1" 132                                                              Content="{Binding}" 133                                                              RestartTransitionOnContentChange="True" 134                                                              Transition="Default"> 135                             <mah:TransitioningContentControl.Resources> 136                                 <DataTemplate DataType="{x:Type mah:HamburgerMenuGlyphItem}"> 137                                     <Image Source="{Binding Glyph, Mode=OneWay, Converter={mah:NullToUnsetValueConverter}}" /> 138                                 </DataTemplate> 139                                 <DataTemplate DataType="{x:Type mah:HamburgerMenuIconItem}"> 140                                     <ContentControl Content="{Binding Tag, Mode=OneWay}" 141                                                         Focusable="True" 142                                                         IsTabStop="False" /> 143                                 </DataTemplate> 144                             </mah:TransitioningContentControl.Resources> 145                         </mah:TransitioningContentControl> 146                     </Grid> 147                 </DataTemplate> 148             </mah:HamburgerMenu.ContentTemplate> 149         </mah:HamburgerMenu> 150  151     </Grid> 152  153 </UserControl>

View Code

导航页面NavigationViewModel页面代码,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

 1 namespace SIMS.NavigationModule.ViewModels  2 {  3     public class NavigationViewModel : BindableBase  4     {  5         #region 属性和构造函数  6   7         private IEventAggregator eventAggregator;  8   9         private List<HamburgerMenuItemBase> navItems; 10  11         public List<HamburgerMenuItemBase> NavItems { get { return navItems; } set { SetProperty(ref navItems, value); } } 12  13         public NavigationViewModel(IEventAggregator eventAggregator) 14         { 15             this.eventAggregator = eventAggregator; 16             navItems = new List<HamburgerMenuItemBase>(); 17             navItems.Add(new HamburgerMenuHeaderItem() { Label = "学生管理"}); 18             navItems.Add(new HamburgerMenuGlyphItem() { Label="学生管理",Tag="Student" ,Glyph="/images/icon_student.png"   }); 19             navItems.Add(new HamburgerMenuGlyphItem() { Label = "班级管理",Tag="Classes"  ,  Glyph = "/images/icon_classes.png" }); 20             navItems.Add(new HamburgerMenuGlyphItem() { Label = "课程管理", Tag="Course" , Glyph = "/images/icon_course.png" }); 21             navItems.Add(new HamburgerMenuGlyphItem() { Label = "成绩管理" ,Tag="Score",  Glyph = "/images/icon_score.png" }); 22             navItems.Add(new HamburgerMenuHeaderItem() { Label = "系统管理",  }); 23             navItems.Add(new HamburgerMenuGlyphItem() { Label = "个人信息",Tag="Personal", Glyph = "/images/icon_personal.png" }); 24             navItems.Add(new HamburgerMenuGlyphItem() { Label = "用户管理",Tag="User", Glyph = "/images/icon_user.png" }); 25             navItems.Add(new HamburgerMenuGlyphItem() { Label = "角色管理",Tag="Role", Glyph = "/images/icon_role.png" }); 26         } 27  28         #endregion 29  30         #region 命令 31  32         private DelegateCommand<object> navCommand; 33  34         public DelegateCommand<object> NavCommand 35         { 36             get 37             { 38                 if (navCommand == null) 39                 { 40  41                     navCommand = new DelegateCommand<object>(Navigation); 42                 } 43                 return navCommand; 44             } 45         } 46  47         private void Navigation(object obj) { 48             var menuItem = (HamburgerMenuItem)obj; 49             if (menuItem != null) {  50                 var tag = menuItem.Tag; 51                 if (tag!=null) {  52                     this.eventAggregator.GetEvent<NavEvent>().Publish(tag.ToString()); 53                 } 54             } 55         } 56  57         #endregion 58     } 59 }

View Code

示例截图

本示例目前主要实现了登录,及主页面布局,导航等功能,如下所示:

WPF开发学生信息管理系统【WPF+Prism+MAH+WebApi】(一)

备注

以上是本文介绍的关于学生信息管理系统的主要内容,旨在抛砖引玉一起学习,共同进步。

贺新郎·九日【作者】刘克庄 【朝代】宋

湛湛长空黑。更那堪、斜风细雨,乱愁如织。老眼平生空四海,赖有高楼百尺。看浩荡、千崖秋色。白发书生神州泪,尽凄凉、不向牛山滴。追往事,去无迹。
少年自负凌云笔。到而今、春华落尽,满怀萧瑟。常恨世人新意少,爱说南朝狂客。把破帽、年年拈出。若对黄花孤负酒,怕黄花、也笑人岑寂。鸿北去,日西匿。