一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

WPF開發(fā)學(xué)生信息管理系統(tǒng)【W(wǎng)PF+Prism+MAH+WebApi】(一)

 老碼識途 2023-10-10 發(fā)布于廣東

最近通過WPF開發(fā)項(xiàng)目,為了對WPF知識點(diǎn)進(jìn)行總結(jié),所以利用業(yè)余時間,開發(fā)一個學(xué)生信息管理系統(tǒng)【Student Information Management System】。本文主要簡述如何通過WPF+Prism+MAH+WebApi進(jìn)行開發(fā)基于三層架構(gòu)的桌面版應(yīng)用程序,僅供學(xué)習(xí)分享使用,如有不足之處,還請指正。

涉及知識點(diǎn)


本次開發(fā)學(xué)生信息管理系統(tǒng),涉及知識點(diǎn)如下:

  • WPF:WPF(Windows Presentation Foundation)是(微軟推出的)基于Windows的用戶界面框架,提供了統(tǒng)一的編程模型,語言和框架,做到了分離界面設(shè)計(jì)人員與開發(fā)人員的工作;WPF提供了全新的多媒體交互用戶圖形界面。相比于WinForm傳統(tǒng)開發(fā),在WPF中,通過核心的MVVM設(shè)計(jì)思想,實(shí)現(xiàn)前后端的分離。

  • Prism:Prism是一個用于在 WPF、Xamarin Form、Uno 平臺和 WinUI 中構(gòu)建松散耦合、可維護(hù)和可測試的 XAML 應(yīng)用程序框架。通過Prism,可以簡化原生MVVM實(shí)現(xiàn)方式,并引入分模塊設(shè)計(jì)思想。在Prism中,每一個功能,都可以設(shè)計(jì)成一個獨(dú)立的模塊,各個模塊之間松耦合,可維護(hù),可測試??蚣苤邪?MVVM、依賴注入、Command、Message Event、導(dǎo)航、彈窗等功能。在后續(xù)程序功能設(shè)計(jì)中,都會用到。

  • MAH:MahApps是一套基于WPF的界面組件,通過該組件,可以使用較小的開發(fā)成本實(shí)現(xiàn)一個相對很好的界面效果。作為后端開發(fā),最頭疼的就是如何設(shè)計(jì)美化頁面,MAH可以讓開發(fā)人員用最少的時間來開發(fā)Metro風(fēng)格的頁面。

  • WebApi:一般是指ASP.NET WebApi 用于快速開發(fā)基于REST風(fēng)格的數(shù)據(jù)接口的框架。

Prism的模塊化思想


在應(yīng)用程序開發(fā)中,如果不采用模塊化思想,那么各個頁面混合在一起,看起雜亂無章,具體如下所示:

當(dāng)我們引入模塊化思想,那么各個模塊的界限將變得清晰,如下所示:

在本文示例的學(xué)生信息管理系統(tǒng)中,就是采用模塊思想,使項(xiàng)目的各個模塊即相對完整,又相互獨(dú)立。如下所示:

在開發(fā)中,引入模塊化思想,通過Prism進(jìn)行代碼布局,如下所示:

MVVM思想


MVVM是Model-View-ViewModel(模型-視圖-視圖模型)的縮寫形式,它通常被用于WPF或Silverlight開發(fā)。MVVM的根本思想就是界面和業(yè)務(wù)功能進(jìn)行分離,View的職責(zé)就是負(fù)責(zé)如何顯示數(shù)據(jù)及發(fā)送命令,ViewModel的功能就是如何提供數(shù)據(jù)和執(zhí)行命令。各司其職,互不影響。我們可以通過下圖來直觀的理解MVVM模式:

 在本示例中,所有開發(fā)都將遵循MVVM思想的設(shè)計(jì)模式進(jìn)行開發(fā),如下所示:

頁面布局


在學(xué)生信息管理系統(tǒng)主界面,根據(jù)傳統(tǒng)的布局方式,主要分為上(Header),中【左(Navigation),右(Main Content)】,下(Footer)四個部分,如下所示:

創(chuàng)建一個模塊


一個模塊是一個獨(dú)立的WPF類庫,在項(xiàng)目中,一個普通的類實(shí)現(xiàn)了IModule接口,就表示一個模塊,以學(xué)生模塊為例,如下所示:

using Prism.Ioc;using Prism.Modularity;using SIMS.StudentModule.ViewModels;using SIMS.StudentModule.Views;using System;
namespace SIMS.StudentModule{ public class StudentModule : IModule { public void OnInitialized(IContainerProvider containerProvider) {
}
public void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterForNavigation<Student, StudentViewModel>(nameof(Student)); } }}

注意:在模塊中,需要實(shí)現(xiàn)兩個接口方法。在此模塊中的RegisterTypes方法中,可以注冊導(dǎo)航,窗口等以及初始化工作。

如果不注冊為導(dǎo)航,而是需要注冊到某一個Region中,則可以在OnInitialized方法中進(jìn)行,以導(dǎo)航模塊為例,如下所示:

using Prism.Ioc;using Prism.Modularity;using Prism.Regions;using SIMS.NavigationModule.Views;using System;
namespace SIMS.NavigationModule{ public class NavigationModule : IModule { public void OnInitialized(IContainerProvider containerProvider) { var regionManager = containerProvider.Resolve<IRegionManager>(); regionManager.RegisterViewWithRegion("NavRegion",typeof(Navigation)); }
public void RegisterTypes(IContainerRegistry containerRegistry) { } }}


View和ViewModel自動適配


View和ViewMode在注冊導(dǎo)航時,可以手動匹配,也可以自動匹配【需要以固定的方式命名才可以自動適配】。自動適配,需要是在UserControl中,增加一句prism:ViewModelLocator.AutoWireViewModel="True"即可,以標(biāo)題頭為例,如下所示:

<UserControl x:Class="SIMS.Views.Header"             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"             xmlns:mc="http://schemas./markup-compatibility/2006"             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"             xmlns:local="clr-namespace:SIMS.Views"             mc:Ignorable="d"             xmlns:prism="http:///"             prism:ViewModelLocator.AutoWireViewModel="True"             xmlns:mahApps="http://metro./winfx/xaml/controls"             d:DesignHeight="100" d:DesignWidth="800">    <UserControl.Resources>        <ResourceDictionary>            <ResourceDictionary.MergedDictionaries>                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />            </ResourceDictionary.MergedDictionaries>        </ResourceDictionary>    </UserControl.Resources>
<Grid Background="{DynamicResource MahApps.Brushes.Accent}"> <Grid.RowDefinitions> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="學(xué)生信息管理系統(tǒng)" Foreground="White" FontSize="32" FontWeight="Bold" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,5"></TextBlock> <StackPanel Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal"> <TextBlock Text="Hello" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="3"></TextBlock> <TextBlock Text="Admin" Foreground="White" Margin="3" FontWeight="Bold"></TextBlock> <TextBlock Text="|" Foreground="White" Margin="3"></TextBlock> <TextBlock Text="Logout" Foreground="White" Margin="3" FontWeight="Bold"></TextBlock> </StackPanel> </Grid>
</UserControl>


彈出模態(tài)窗口


在Prism中,模塊中的視圖都是以UserControl的形式存在,那么如果需要彈出窗體頁面,就需要在ViewModel中,實(shí)現(xiàn)IDialogAware接口,以Login登錄窗口為例,如下所示:

using Prism.Regions;using Prism.Services.Dialogs;using SIMS.Views;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;
namespace SIMS.ViewModels{ public class LoginViewModel : BindableBase, IDialogAware { private IRegionManager _regionManager; private IContainerExtension _container;
private string userName;
public string UserName { get { return userName; } set {SetProperty(ref userName , value); } }
private string password;
public string Password { get { return password; } set { SetProperty(ref password , value); } }

public LoginViewModel(IContainerExtension container,IRegionManager regionManager) { this._container = container; this._regionManager = regionManager; }
private void InitInfo() { var footer = _container.Resolve<Footer>(); IRegion footerRegion = _regionManager.Regions["LoginFooterRegion"]; footerRegion.Add(footer); }
#region 命令
private DelegateCommand loadedCommand;
public DelegateCommand LoadedCommand { get { if (loadedCommand == null) { loadedCommand = new DelegateCommand(Loaded); } return loadedCommand; } }
private void Loaded() { //InitInfo(); }
private DelegateCommand loginCommand;
public DelegateCommand LoginCommand { get { if (loginCommand == null) { loginCommand = new DelegateCommand(Login); } return loginCommand; } }
private void Login() { if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(Password)) { MessageBox.Show("用戶名或密碼為空,請確認(rèn)"); return; } if (UserName == "admin" && Password == "abc123") { CloseWindow(); } else { MessageBox.Show("用戶名密碼不正確,請確認(rèn)"); return; } }
private DelegateCommand cancelCommand;
public DelegateCommand CancelCommand { get { if (cancelCommand == null) { cancelCommand = new DelegateCommand(Cancel); } return cancelCommand; } }
private void Cancel() { RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)); }
#endregion
#region DialogAware接口
public string Title => "SIMS-Login";
public event Action<IDialogResult> RequestClose;
/// <summary> /// 成功時關(guān)閉窗口 /// </summary> public void CloseWindow() { RequestClose?.Invoke(new DialogResult(ButtonResult.OK)); }
public bool CanCloseDialog() { return true; }
public void OnDialogClosed() { //當(dāng)關(guān)閉時 RequestClose?.Invoke(new DialogResult(ButtonResult.Cancel)); }
public void OnDialogOpened(IDialogParameters parameters) { //傳遞解析參數(shù) }
#endregion }}

實(shí)現(xiàn)了IDialogAware接口,表示以窗口的形態(tài)出現(xiàn),在需要彈出窗口的地方進(jìn)行調(diào)用即可。如下所示:

public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) {    this._container = container;    this._regionManager = regionManager;    this.eventAggregator = eventAggregator;    this._dialogService = dialogService;    //彈出登錄窗口    this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow");    this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation);}

注意:MetroDialogWindow是自定義個一個Metro風(fēng)格的窗口,如果為空,則采用默認(rèn)窗口風(fēng)格。

模塊間交互


按照模塊化設(shè)計(jì)思想,雖然各個模塊之間相互獨(dú)立,但是難免為遇到模塊之間進(jìn)行交互的情況,所以Prism提供了事件聚合器,通過命令的發(fā)布和訂閱來實(shí)現(xiàn)模塊間的數(shù)據(jù)交互。以導(dǎo)航模塊為例,當(dāng)點(diǎn)擊某一個導(dǎo)航時,發(fā)布一個命令,在主窗口訂閱此事件,當(dāng)收到事件時,將此導(dǎo)航對應(yīng)的頁面渲染到主頁面區(qū)域中。步驟如下:

1. 定義一個事件

using Prism.Events;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;
namespace SIMS.Utils.Events{ /// <summary> /// 導(dǎo)航事件 /// </summary> public class NavEvent : PubSubEvent<string> { }}

2. 發(fā)布事件

用戶點(diǎn)擊導(dǎo)航菜單時,觸發(fā)NavCommand,然后發(fā)布命令。

private DelegateCommand<object> navCommand;
public DelegateCommand<object> NavCommand{ get { if (navCommand == null) {
navCommand = new DelegateCommand<object>(Navigation); } return navCommand; }}
private void Navigation(object obj) { var menuItem = (HamburgerMenuItem)obj; if (menuItem != null) { var tag = menuItem.Tag; if (tag!=null) { this.eventAggregator.GetEvent<NavEvent>().Publish(tag.ToString()); } }}

3. 訂閱命令

在主窗口,訂閱命令,當(dāng)收到命令時,再初始化模塊信息,如下所示:

namespace SIMS.ViewModels{    public class MainWindowViewModel:BindableBase    {
private IEventAggregator eventAggregator; private IContainerExtension _container; private IRegionManager _regionManager; private IDialogService _dialogService; public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) { this._container = container; this._regionManager = regionManager; this.eventAggregator = eventAggregator; this._dialogService = dialogService; //彈出登錄窗口 this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow"); this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation); }
private void LoginCallback(IDialogResult dialogResult) { if (dialogResult.Result != ButtonResult.OK) { Application.Current.Shutdown(); } }
#region 事件和命令
private DelegateCommand loadedCommand;
public DelegateCommand LoadedCommand { get { if (loadedCommand == null) { loadedCommand = new DelegateCommand(Loaded); } return loadedCommand; } }
private void Loaded() { InitInfo(); }



private void InitInfo() { var header = _container.Resolve<Header>(); IRegion headerRegion = _regionManager.Regions["HeaderRegion"]; headerRegion.Add(header); // var footer = _container.Resolve<Footer>(); IRegion footerRegion = _regionManager.Regions["FooterRegion"]; footerRegion.Add(footer);
var welcome = _container.Resolve<Welcome>(); IRegion welcomeRegion = _regionManager.Regions["ContentRegion"]; welcomeRegion.Add(welcome); }
private void Navigation(string source) { _regionManager.RequestNavigate("ContentRegion", source); //MessageBox.Show(source); }
#endregion }}

注意:一般情況下,只有在不同模塊時,才使用事件聚合器進(jìn)行事件的訂閱和發(fā)布。如果是同一模塊,則沒有必要。

核心代碼


模塊的配置

各個模塊之間相互獨(dú)立,所以在主模塊中進(jìn)行加載時,需要先進(jìn)行配置。模塊加載的方式有很多種,本例采用App.config配置方式,如下所示:

<?xml version="1.0" encoding="utf-8" ?><configuration>    <configSections>        <section name="modules" type="Prism.Modularity.ModulesConfigurationSection, Prism.Wpf" />    </configSections>    <startup>    </startup>    <modules>        <module assemblyFile="SIMS.NavigationModule.dll" moduleType="SIMS.NavigationModule.NavigationModule, SIMS.NavigationModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="NavigationModule" startupLoaded="True" />        <module assemblyFile="SIMS.ScoreModule.dll" moduleType="SIMS.ScoreModule.ScoreModule, SIMS.ScoreModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ScoreModule" startupLoaded="True" />        <module assemblyFile="SIMS.StudentModule.dll" moduleType="SIMS.StudentModule.StudentModule, SIMS.StudentModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="StudentModule" startupLoaded="True" />        <module assemblyFile="SIMS.ClassesModule.dll" moduleType="SIMS.ClassesModule.ClassesModule, SIMS.ClassesModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ClassesModule" startupLoaded="True" />        <module assemblyFile="SIMS.CourseModule.dll" moduleType="SIMS.CourseModule.CourseModule, SIMS.CourseModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="CourseModule" startupLoaded="True" />        <module assemblyFile="SIMS.SysManagementModule.dll" moduleType="SIMS.SysManagementModule.SysManagementModule, SIMS.SysManagementModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="SysManagementModule" startupLoaded="True" />    </modules></configuration>

啟動入口App.xaml,可以用來配置資源字典等初始化操作,如下所示:

<prism:PrismApplication x:Class="SIMS.App"             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"             xmlns:local="clr-namespace:SIMS"             xmlns:mah="http://metro./winfx/xaml/controls"             xmlns:prism="http:///"             >    <Application.Resources>        <ResourceDictionary>            <ResourceDictionary.MergedDictionaries>                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />                <ResourceDictionary Source="/Icons/Icons.xaml"></ResourceDictionary>            </ResourceDictionary.MergedDictionaries>        </ResourceDictionary>    </Application.Resources></prism:PrismApplication>

啟動入口App.xaml.cs,應(yīng)用程序需要繼承PrismApplication基類,才是一個Prism應(yīng)用程序。在此文件中初始化App.config中配置的模塊。如下所示:

namespace SIMS{    /// <summary>    /// Interaction logic for App.xaml    /// </summary>    public partial class App : PrismApplication    {        protected override Window CreateShell()        {            return Container.Resolve<MainWindow>();        }
protected override void RegisterTypes(IContainerRegistry containerRegistry) { containerRegistry.RegisterDialog<Login, LoginViewModel>(nameof(Login)); containerRegistry.Register<IDialogWindow, MetroDialogWindow>("MetroDialogWindow"); }
protected override IModuleCatalog CreateModuleCatalog() { return new ConfigurationModuleCatalog(); } }}

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

<mahApps:MetroWindow x:Class="SIMS.Views.MainWindow"        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./markup-compatibility/2006"        xmlns:local="clr-namespace:SIMS"        mc:Ignorable="d"        xmlns:prism="http:///"        xmlns:mahApps="http://metro./winfx/xaml/controls"        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"        prism:ViewModelLocator.AutoWireViewModel="True"        mahApps:Title="SIMS--Student Information Management System"        mahApps:TitleCharacterCasing="Normal"        d:DesignHeight="1080" d:DesignWidth="1920"         WindowState="Maximized">    <Window.Resources>        <ResourceDictionary>            <ResourceDictionary.MergedDictionaries>                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />            </ResourceDictionary.MergedDictionaries>        </ResourceDictionary>    </Window.Resources>
<i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> <Grid ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <ContentControl prism:RegionManager.RegionName="HeaderRegion" Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" MinHeight="80"></ContentControl> <ContentControl prism:RegionManager.RegionName="NavRegion" Grid.Row="1" Grid.Column="0"></ContentControl> <ContentControl prism:RegionManager.RegionName="ContentRegion" Grid.Row="1" Grid.Column="1"></ContentControl> <ContentControl prism:RegionManager.RegionName="FooterRegion" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" MinHeight="50"></ContentControl> </Grid></mahApps:MetroWindow>

主窗口MainWindowViewModel,代碼如下:

namespace SIMS.ViewModels{    public class MainWindowViewModel:BindableBase    {
private IEventAggregator eventAggregator; private IContainerExtension _container; private IRegionManager _regionManager; private IDialogService _dialogService; public MainWindowViewModel(IContainerExtension container, IRegionManager regionManager, IEventAggregator eventAggregator,IDialogService dialogService) { this._container = container; this._regionManager = regionManager; this.eventAggregator = eventAggregator; this._dialogService = dialogService; //彈出登錄窗口 this._dialogService.ShowDialog("Login", null, LoginCallback, "MetroDialogWindow"); this.eventAggregator.GetEvent<NavEvent>().Subscribe(Navigation); }
private void LoginCallback(IDialogResult dialogResult) { if (dialogResult.Result != ButtonResult.OK) { Application.Current.Shutdown(); } }
#region 事件和命令
private DelegateCommand loadedCommand;
public DelegateCommand LoadedCommand { get { if (loadedCommand == null) { loadedCommand = new DelegateCommand(Loaded); } return loadedCommand; } }
private void Loaded() { InitInfo(); }



private void InitInfo() { var header = _container.Resolve<Header>(); IRegion headerRegion = _regionManager.Regions["HeaderRegion"]; headerRegion.Add(header); // var footer = _container.Resolve<Footer>(); IRegion footerRegion = _regionManager.Regions["FooterRegion"]; footerRegion.Add(footer);
var welcome = _container.Resolve<Welcome>(); IRegion welcomeRegion = _regionManager.Regions["ContentRegion"]; welcomeRegion.Add(welcome); }
private void Navigation(string source) { _regionManager.RequestNavigate("ContentRegion", source); //MessageBox.Show(source); }
#endregion }}

導(dǎo)航頁面Navigation.xaml頁面采用MAH的Hamburger菜單,如下所示:

<UserControl x:Class="SIMS.NavigationModule.Views.Navigation"             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:iconPacks="http://metro./winfx/xaml/iconpacks"             xmlns:local="clr-namespace:SIMS.NavigationModule.Views"             xmlns:mah="http://metro./winfx/xaml/controls"             xmlns:mc="http://schemas./markup-compatibility/2006"             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"             xmlns:prism="http:///"             prism:ViewModelLocator.AutoWireViewModel="True"             d:DesignHeight="300"             d:DesignWidth="240"             mc:Ignorable="d">
<UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" /> <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> </ResourceDictionary.MergedDictionaries> <!-- This is the template for all menu items. In this sample we use the glyph items. --> <DataTemplate x:Key="HamburgerMenuItem" DataType="{x:Type mah:HamburgerMenuGlyphItem}"> <DockPanel Height="48" LastChildFill="True"> <Grid x:Name="IconPart" DockPanel.Dock="Left">
<Image Margin="12" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding Glyph}" /> </Grid> <TextBlock x:Name="TextPart" VerticalAlignment="Center" FontSize="16" Text="{Binding Label}" /> </DockPanel> </DataTemplate>

<DataTemplate x:Key="HamburgerOptionsMenuItem" DataType="{x:Type mah:HamburgerMenuIconItem}"> <DockPanel Height="48" LastChildFill="True"> <ContentControl x:Name="IconPart" Content="{Binding Icon}" DockPanel.Dock="Left" Focusable="False" IsTabStop="False" /> <TextBlock x:Name="TextPart" VerticalAlignment="Center" FontSize="16" Text="{Binding Label}" /> </DockPanel> </DataTemplate> </ResourceDictionary> </UserControl.Resources>
<Grid Background="{DynamicResource MahApps.Brushes.Accent}"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <mah:HamburgerMenu x:Name="HamburgerMenuControl" Grid.Column="0" DisplayMode="CompactOverlay" Margin="0" IsPaneOpen="True"
HamburgerButtonHelpText="Please click me" HamburgerButtonClick="HamburgerMenuControl_HamburgerButtonClick" ItemTemplate="{StaticResource HamburgerMenuItem}" OptionsItemTemplate="{StaticResource HamburgerOptionsMenuItem}" ItemsSource="{Binding NavItems}" VerticalScrollBarOnLeftSide="False"> <i:Interaction.Triggers> <i:EventTrigger EventName="ItemInvoked"> <i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="{Binding ElementName=HamburgerMenuControl, Path=SelectedItem}" ></i:InvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> <!-- Header --> <mah:HamburgerMenu.HamburgerMenuHeaderTemplate> <DataTemplate> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" Foreground="White" Text="" /> </DataTemplate> </mah:HamburgerMenu.HamburgerMenuHeaderTemplate> <mah:HamburgerMenu.OptionsItemsSource> <mah:HamburgerMenuItemCollection>
<mah:HamburgerMenuIconItem x:Name="AboutOption"
Label="About"> <mah:HamburgerMenuIconItem.Icon> <iconPacks:PackIconMaterial Width="22" Height="22" HorizontalAlignment="Center" VerticalAlignment="Center" Kind="Help" /> </mah:HamburgerMenuIconItem.Icon> <mah:HamburgerMenuIconItem.Tag> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="28" FontWeight="Bold"> About </TextBlock> </mah:HamburgerMenuIconItem.Tag> </mah:HamburgerMenuIconItem>
</mah:HamburgerMenuItemCollection> </mah:HamburgerMenu.OptionsItemsSource> <!-- Content --> <mah:HamburgerMenu.ContentTemplate> <DataTemplate> <Grid x:Name="ContentGrid"> <Grid.RowDefinitions> <RowDefinition Height="48" /> <RowDefinition /> </Grid.RowDefinitions> <Border Grid.Row="0" Margin="-1 0 -1 0" Background="#7A7A7A"> <TextBlock x:Name="Header" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" Foreground="White" Text="{Binding Label}" /> </Border> <mah:TransitioningContentControl Grid.Row="1" Content="{Binding}" RestartTransitionOnContentChange="True" Transition="Default"> <mah:TransitioningContentControl.Resources> <DataTemplate DataType="{x:Type mah:HamburgerMenuGlyphItem}"> <Image Source="{Binding Glyph, Mode=OneWay, Converter={mah:NullToUnsetValueConverter}}" /> </DataTemplate> <DataTemplate DataType="{x:Type mah:HamburgerMenuIconItem}"> <ContentControl Content="{Binding Tag, Mode=OneWay}" Focusable="True" IsTabStop="False" /> </DataTemplate> </mah:TransitioningContentControl.Resources> </mah:TransitioningContentControl> </Grid> </DataTemplate> </mah:HamburgerMenu.ContentTemplate> </mah:HamburgerMenu>
</Grid>
</UserControl>

導(dǎo)航頁面NavigationViewModel頁面代碼,如下所示:

namespace SIMS.NavigationModule.ViewModels{    public class NavigationViewModel : BindableBase    {        #region 屬性和構(gòu)造函數(shù)
private IEventAggregator eventAggregator;
private List<HamburgerMenuItemBase> navItems;
public List<HamburgerMenuItemBase> NavItems { get { return navItems; } set { SetProperty(ref navItems, value); } }
public NavigationViewModel(IEventAggregator eventAggregator) { this.eventAggregator = eventAggregator; navItems = new List<HamburgerMenuItemBase>(); navItems.Add(new HamburgerMenuHeaderItem() { Label = "學(xué)生管理"}); navItems.Add(new HamburgerMenuGlyphItem() { Label="學(xué)生管理",Tag="Student" ,Glyph="/images/icon_student.png" }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "班級管理",Tag="Classes" , Glyph = "/images/icon_classes.png" }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "課程管理", Tag="Course" , Glyph = "/images/icon_course.png" }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "成績管理" ,Tag="Score", Glyph = "/images/icon_score.png" }); navItems.Add(new HamburgerMenuHeaderItem() { Label = "系統(tǒng)管理", }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "個人信息",Tag="Personal", Glyph = "/images/icon_personal.png" }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "用戶管理",Tag="User", Glyph = "/images/icon_user.png" }); navItems.Add(new HamburgerMenuGlyphItem() { Label = "角色管理",Tag="Role", Glyph = "/images/icon_role.png" }); }
#endregion
#region 命令
private DelegateCommand<object> navCommand;
public DelegateCommand<object> NavCommand { get { if (navCommand == null) {
navCommand = new DelegateCommand<object>(Navigation); } return navCommand; } }
private void Navigation(object obj) { var menuItem = (HamburgerMenuItem)obj; if (menuItem != null) { var tag = menuItem.Tag; if (tag!=null) { this.eventAggregator.GetEvent<NavEvent>().Publish(tag.ToString()); } } }
#endregion }}


示例截圖


本示例目前主要實(shí)現(xiàn)了登錄,及主頁面布局,導(dǎo)航等功能,如下所示:


備注


以上是本文介紹的關(guān)于學(xué)生信息管理系統(tǒng)的主要內(nèi)容,旨在拋磚引玉一起學(xué)習(xí),共同進(jìn)步。

學(xué)習(xí)編程,從關(guān)注【老碼識途】開始?。?!

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    日系韩系还是欧美久久| 国产精品香蕉一级免费| 亚洲免费观看一区二区三区| 国产不卡免费高清视频| 久久亚洲精品成人国产| 国产又大又黄又粗又免费| 亚洲欧洲日韩综合二区| 欧美日韩国产成人高潮| 欧美丝袜诱惑一区二区| 内射精品欧美一区二区三区久久久| 人妻精品一区二区三区视频免精| 国产又粗又猛又爽又黄| 好吊妞视频这里有精品| 欧美一区日韩一区日韩一区| 少妇人妻一级片一区二区三区| 亚洲国产91精品视频| 色婷婷亚洲精品综合网| 免费国产成人性生活生活片| 欧美黑人精品一区二区在线| 亚洲视频偷拍福利来袭| 视频一区日韩经典中文字幕| 夫妻激情视频一区二区三区| 91久久精品国产成人| 日韩人妻少妇一区二区| 欧美人妻少妇精品久久性色 | 欧美精品久久一二三区| 97人妻精品免费一区二区| 麻豆视传媒短视频免费观看 | 精品推荐国产麻豆剧传媒| 欧美一区二区三区性视频| 国产欧美日韩在线精品一二区| 午夜福利激情性生活免费视频| 一区二区三区人妻在线| 久久精品国产第一区二区三区| 日韩在线精品视频观看| 色综合视频一区二区观看| 国产亚洲视频香蕉一区| 99福利一区二区视频| 少妇被粗大进猛进出处故事| 国产一区欧美一区日本道| 国产精品欧美激情在线观看|