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

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

最近通过WPF开发项目,为了对WPF知识点进行总结,所以利用业余时间,开发一个学生信息管理系统【Student Information Management System】。前三篇文章进行了框架搭建和模块划分,后台WebApi接口编写,以及课程管理模块开发,本文在前三篇基础之上,继续深入开发学生信息管理系统的班级管理和学生管理模块,通过本篇文章,将继续巩固之前的知识点,本文仅供学习分享使用,如有不足之处,还请指正。

最近通过WPF开发项目,为了对WPF知识点进行总结,所以利用业余时间,开发一个学生信息管理系统【Student Information Management System】。前三篇文章进行了框架搭建和模块划分,后台WebApi接口编写,以及课程管理模块开发,本文在前三篇基础之上,继续深入开发学生信息管理系统的班级管理和学生管理模块,通过本篇文章,将继续巩固之前的知识点,本文仅供学习分享使用,如有不足之处,还请指正。

涉及知识点

由于班级管理和学生管理的服务端开发,在第二篇文章中以后介绍,所以本篇专注介绍客户端功能的开发。涉及知识点如下:

  1. WPF开发中TextBlock,TextBox,DataGrid,Combox等控件的基础使用以及数据绑定等操作。
  2. MAH样式的使用,在本示例中MAH主要用于统一页面风格,提高用户体验。
  3. HttpClient使用,主要用于访问服务端提供的接口。

业务逻辑

首先班级管理和学生管理既有关联,又相互独立,不像课程管理模块独立存在,不与其他模块存在依赖。所以两个模块一起放在一篇文章进行讲解。关系如下:

  1. 学生属于某一班级之学生,所以学生中包含班级信息。
  2. 班级中存在班长,班长又属于学生的一个实体。

班级管理

1. 接口访问类ClassesHttpUtil

班级数据表结构和服务接口,在第二篇文章中已有介绍,如有疑问,可前往参考。接口访问类用于封装访问服务端提供的接口。如下所示:

 1 namespace SIMS.Utils.Http  2 {  3     public class ClassesHttpUtil:HttpUtil  4     {  5         /// <summary>  6         /// 通过id查询学生信息  7         /// </summary>  8         /// <param name="id"></param>  9         /// <returns></returns> 10         public static ClassesEntity GetClasses(int id) 11         { 12             Dictionary<string, object> data = new Dictionary<string, object>(); 13             data["id"] = id; 14             var str = Get(UrlConfig.CLASSES_GETCLASSES, data); 15             var classes = StrToObject<ClassesEntity>(str); 16             return classes; 17         } 18  19         public static PagedRequest<ClassesEntity> GetClassess(string? dept, string? grade, int pageNum, int pageSize) 20         { 21             Dictionary<string, object> data = new Dictionary<string, object>(); 22             data["dept"] = dept; 23             data["grade"] = grade; 24             data["pageNum"] = pageNum; 25             data["pageSize"] = pageSize; 26             var str = Get(UrlConfig.CLASSES_GETCLASSESS, data); 27             var classess = StrToObject<PagedRequest<ClassesEntity>>(str); 28             return classess; 29         } 30  31         public static bool AddClasses(ClassesEntity classes) { 32             var ret = Post<ClassesEntity>(UrlConfig.CLASSES_ADDCLASSES, classes); 33             return int.Parse(ret)==0; 34         } 35  36         public static bool UpdateClasses(ClassesEntity classes) { 37             var ret = Put<ClassesEntity>(UrlConfig.CLASSES_UPDATECLASSES, classes); 38             return int.Parse(ret) == 0; 39         } 40  41         public static bool DeleteClasses(int Id) 42         { 43             Dictionary<string,  string> data = new Dictionary<string, string>(); 44             data["Id"] = Id.ToString(); 45             var ret = Delete(UrlConfig.CLASSES_DELETECLASSES, data); 46             return int.Parse(ret) == 0; 47         } 48     } 49 }

2. 客户端页面视图

班级管理的客户端页面视图共两个,一个查询列表页面,一个新增编辑页面,共同组成了班级管理的增删改查。

查询班级列表页面,涉及知识点如下所示:

  1. 查询条件或者列表中数据列展示,通过数据绑定Binding的方式与ViewModel进行交互,即点击查询按钮,不再传递参数,因为ViewModel中的属性已经同步更新。
  2. ViewModel中并非所有属性都可实现双向绑定,必须是实现具有通知功能的属性才可以。在Prism框架中,通过BindableBase的SetProperty方法可以快速实现。
  3. View视图中如果控件存在Command命令,则可以直接绑定,如果不存在,则可以i:Interaction.Triggers将事件转换为命令,如Load事件等。
  4. 在列表中,如果需要添加按钮,可以通过DataTemplate进行数据定制。

查询班级页面代码,如下所示:

  1 <UserControl x:Class="SIMS.ClassesModule.Views.Classes"   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.ClassesModule.Views"   7              xmlns:prism="http://prismlibrary.com/"   8              xmlns:i="http://schemas.microsoft.com/xaml/behaviors"   9              xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls"  10              xmlns:ctrls ="clr-namespace:SIMS.Utils.Controls;assembly=SIMS.Utils"  11              prism:ViewModelLocator.AutoWireViewModel="True"  12              mc:Ignorable="d"   13              d:DesignHeight="450" d:DesignWidth="800">  14     <UserControl.Resources>  15         <ResourceDictionary>  16             <ResourceDictionary.MergedDictionaries>  17                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />  18                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />  19                 <ResourceDictionary>  20                     <Style x:Key="LinkButton" TargetType="Button">  21                         <Setter Property="Background" Value="White"></Setter>  22                         <Setter Property="Cursor" Value="Hand"></Setter>  23                         <Setter Property="Margin" Value="3"></Setter>  24                         <Setter Property="MinWidth" Value="80"></Setter>  25                         <Setter Property="MinHeight" Value="25"></Setter>  26                         <Setter Property="BorderThickness" Value="0 0 0 0"></Setter>  27                     </Style>  28                 </ResourceDictionary>  29             </ResourceDictionary.MergedDictionaries>  30         </ResourceDictionary>  31     </UserControl.Resources>  32     <i:Interaction.Triggers>  33         <i:EventTrigger EventName="Loaded">  34             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction>  35         </i:EventTrigger>  36     </i:Interaction.Triggers>  37     <Grid>  38         <Grid.RowDefinitions>  39             <RowDefinition Height="Auto"></RowDefinition>  40             <RowDefinition Height="Auto"></RowDefinition>  41             <RowDefinition Height="*"></RowDefinition>  42             <RowDefinition Height="Auto"></RowDefinition>  43         </Grid.RowDefinitions>  44         <TextBlock Text="班级信息" FontSize="20" Background="AliceBlue" Margin="2"></TextBlock>  45         <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center">  46             <TextBlock Text="专业" VerticalAlignment="Center" Margin="2"></TextBlock>  47             <TextBox Margin="4" MinWidth="120" Height="30"  48                      Text="{Binding Dept}"  49                              HorizontalContentAlignment="Stretch"  50                              mahApps:TextBoxHelper.ClearTextButton="True"  51                              mahApps:TextBoxHelper.Watermark="专业"  52                              mahApps:TextBoxHelper.WatermarkAlignment="Left"  53                              SpellCheck.IsEnabled="True" />  54             <TextBlock Text="年级" VerticalAlignment="Center" Margin="2"></TextBlock>  55             <TextBox Margin="4" MinWidth="120" Height="30"  56                      Text="{Binding Grade}"  57                              HorizontalContentAlignment="Stretch"  58                              mahApps:TextBoxHelper.ClearTextButton="True"  59                              mahApps:TextBoxHelper.Watermark="年级"  60                              mahApps:TextBoxHelper.WatermarkAlignment="Left"  61                              SpellCheck.IsEnabled="True" />  62             <Button Content="查询" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Width="120" Height="30" Margin="3" Command="{Binding QueryCommand}"></Button>  63             <Button Content="新增" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Width="120" Height="30" Margin="3" Command="{Binding AddCommand}"></Button>  64         </StackPanel>  65         <DataGrid x:Name="dgClasses"  66                   Grid.Row="2"  67                   Grid.Column="0"  68                   Margin="2"  69                   AutoGenerateColumns="False"  70                   CanUserAddRows="False"  71                   CanUserDeleteRows="False"  72                   ItemsSource="{Binding Classes}"  73                   RowHeaderWidth="0">  74             <DataGrid.Columns>  75                 <DataGridTextColumn Binding="{Binding Dept}" Header="专业" Width="*" />  76                 <DataGridTextColumn Binding="{Binding Grade}" Header="年级" Width="*"/>  77                 <DataGridTextColumn Binding="{Binding Name}" Header="班级" Width="*"/>  78                 <DataGridTextColumn Binding="{Binding HeadTeacher}" Header="班主任" Width="*"/>  79                 <DataGridTextColumn Binding="{Binding MonitorName}" Header="班长" Width="*" />  80                 <DataGridTemplateColumn Header="操作" Width="*">  81                     <DataGridTemplateColumn.CellTemplate>  82                         <DataTemplate>  83                             <StackPanel Orientation="Horizontal">  84                                 <Button  Content="Edit" Style="{StaticResource LinkButton}" Command="{Binding RelativeSource={RelativeSource  AncestorType=DataGrid,  Mode=FindAncestor}, Path=DataContext.EditCommand}" CommandParameter="{Binding Id}">  85                                     <Button.Template>  86                                         <ControlTemplate TargetType="Button">  87                                             <TextBlock TextDecorations="Underline" HorizontalAlignment="Center">  88                                                 <ContentPresenter />  89                                             </TextBlock>  90                                         </ControlTemplate>  91                                     </Button.Template>  92                                 </Button>  93                                 <Button Content="Delete" Style="{StaticResource LinkButton}" Command="{Binding RelativeSource={RelativeSource  AncestorType=DataGrid,  Mode=FindAncestor}, Path=DataContext.DeleteCommand}" CommandParameter="{Binding Id}">  94                                     <Button.Template>  95                                         <ControlTemplate TargetType="Button">  96                                             <TextBlock TextDecorations="Underline" HorizontalAlignment="Center">  97                                                 <ContentPresenter />  98                                             </TextBlock>  99                                         </ControlTemplate> 100                                     </Button.Template> 101                                 </Button> 102                             </StackPanel> 103                         </DataTemplate> 104                     </DataGridTemplateColumn.CellTemplate> 105                 </DataGridTemplateColumn> 106             </DataGrid.Columns> 107         </DataGrid> 108         <ctrls:PageControl Grid.Row="3" DataContext="{Binding}" ></ctrls:PageControl> 109     </Grid> 110 </UserControl>

新增编辑页面

班级的新增功能和编辑功能,共用一个页面,涉及知识点如下所示:

  1. 在新增编辑的ViewModel中,班级实体是一个属性,所以在视图控件中进行数据绑定时,需要带上属性名,如:Classes.Name 。
  2. 班长列表在新增班级时尚无对应学生,可为空,待维护学生后,可通过学生列表进行选择即可。
  3. 班长列表为Combox下拉框,绑定的是学生实体列表,但客户端只需看到学生姓名即可,所以需要重写DataTemplate,只显示学生姓名。

新增班级信息视图,具体代码如下所示:

 1 <UserControl x:Class="SIMS.ClassesModule.Views.AddEditClasses"  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.ClassesModule.Views"  7              mc:Ignorable="d"  8              xmlns:i="http://schemas.microsoft.com/xaml/behaviors"  9              xmlns:mahApps ="http://metro.mahapps.com/winfx/xaml/controls" 10              xmlns:prism="http://prismlibrary.com/"       11              d:DesignHeight="400" d:DesignWidth="600"> 12     <prism:Dialog.WindowStyle> 13         <Style TargetType="Window"> 14             <Setter Property="Width" Value="600"></Setter> 15             <Setter Property="Height" Value="400"></Setter> 16         </Style> 17     </prism:Dialog.WindowStyle> 18     <UserControl.Resources> 19         <ResourceDictionary> 20             <ResourceDictionary.MergedDictionaries> 21                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> 22                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> 23             </ResourceDictionary.MergedDictionaries> 24         </ResourceDictionary> 25     </UserControl.Resources> 26     <i:Interaction.Triggers> 27         <i:EventTrigger EventName="Loaded"> 28             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction> 29         </i:EventTrigger> 30     </i:Interaction.Triggers> 31     <Grid> 32         <Grid.ColumnDefinitions> 33             <ColumnDefinition Width="0.2*"></ColumnDefinition> 34             <ColumnDefinition Width="Auto"></ColumnDefinition> 35             <ColumnDefinition Width="*"></ColumnDefinition> 36             <ColumnDefinition Width="0.2*"></ColumnDefinition> 37         </Grid.ColumnDefinitions> 38         <Grid.RowDefinitions> 39             <RowDefinition></RowDefinition> 40             <RowDefinition></RowDefinition> 41             <RowDefinition></RowDefinition> 42             <RowDefinition></RowDefinition> 43             <RowDefinition></RowDefinition> 44             <RowDefinition></RowDefinition> 45             <RowDefinition></RowDefinition> 46         </Grid.RowDefinitions> 47  48  49         <TextBlock Text="专业" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="3"></TextBlock> 50         <TextBox Grid.Row="0" Grid.Column="2" MinWidth="120" Height="35"  VerticalAlignment="Center" Margin="3" Text="{Binding Classes.Dept}"></TextBox> 51         <TextBlock Text="年级" Grid.Row="1" Grid.Column="1"  VerticalAlignment="Center" Margin="3"></TextBlock> 52         <TextBox Grid.Row="1" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Classes.Grade}"></TextBox> 53         <TextBlock Text="班级" Grid.Row="2" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 54         <TextBox Grid.Row="2" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Classes.Name}"></TextBox> 55         <TextBlock Text="班主任" Grid.Row="3" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 56         <TextBox Grid.Row="3" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Classes.HeadTeacher}"></TextBox> 57         <TextBlock Text="班长" Grid.Row="4" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 58         <ComboBox Grid.Row="4" Grid.Column="2" MinWidth="120" Height="35" ItemsSource="{Binding Monitors}" mahApps:TextBoxHelper.ClearTextButton="True" SelectedItem="{Binding Monitor}"> 59             <ComboBox.ItemTemplate> 60                 <DataTemplate> 61                     <TextBlock Text="{Binding Name}"></TextBlock> 62                 </DataTemplate> 63             </ComboBox.ItemTemplate> 64         </ComboBox> 65         <StackPanel Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="3"> 66             <Button Content="取消" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding CancelCommand}"></Button> 67             <Button Content="保存" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding SaveCommand}"></Button> 68         </StackPanel> 69         <TextBlock Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" Text="注意:新增班级时,班长可空,等维护学生后,再设置班长。" Foreground="Red"></TextBlock> 70     </Grid> 71 </UserControl>

3. 客户端ViewModel

班级管理模块,ViewModel和视图对应,也分为查询列表ViewModel和新增编辑ViewModel,如下所示:

ClassesViewModel页面代码分为三部分:

  1. 属性和构造函数,主要用于数据绑定,如查询条件,列表等。所有属性的set赋值时,均采用SetProperty进行赋值。
  2. 命令Command,如查询,新增,编辑,删除命令等。所有命令可以定义成DelegateCommand类型。
  3. 分页部分,因分页功能代码大同小异,所以此处略去。

ClassesViewModel具体代码如下所示:

  1 namespace SIMS.ClassesModule.ViewModels   2 {   3     public class ClassesViewModel :BindableBase   4     {   5         #region 属性及构造函数   6    7         /// <summary>   8         /// 专业   9         /// </summary>  10         private string dept;  11   12         public string Dept  13         {  14             get { return dept; }  15             set { SetProperty(ref dept , value); }  16         }  17   18         /// <summary>  19         /// 年级  20         /// </summary>  21         private string grade;  22   23         public string Grade  24         {  25             get { return grade; }  26             set { SetProperty(ref grade , value); }  27         }  28   29   30   31         private ObservableCollection<ClassesInfo> classes;  32   33         public ObservableCollection<ClassesInfo> Classes  34         {  35             get { return classes; }  36             set { SetProperty(ref classes, value); }  37         }  38   39         private IDialogService dialogService;  40   41         public ClassesViewModel(IDialogService dialogService)  42         {  43             this.dialogService = dialogService;  44             this.pageNum = 1;  45             this.pageSize = 20;  46         }  47   48         private void InitInfo()  49         {  50             Classes = new ObservableCollection<ClassesInfo>();  51             var pagedRequst = ClassesHttpUtil.GetClassess(this.Dept,this.Grade, this.pageNum, this.pageSize);  52             var entities = pagedRequst.items;  53             Classes.AddRange(entities.Select(r=>new ClassesInfo(r)));  54             //  55             this.TotalCount = pagedRequst.count;  56             this.TotalPage = ((int)Math.Ceiling(this.TotalCount * 1.0 / this.pageSize));  57         }  58   59         #endregion  60   61         #region 事件  62   63         private DelegateCommand loadedCommand;  64   65         public DelegateCommand LoadedCommand  66         {  67             get  68             {  69                 if (loadedCommand == null)  70                 {  71                     loadedCommand = new DelegateCommand(Loaded);  72                 }  73                 return loadedCommand;  74             }  75         }  76   77         private void Loaded()  78         {  79             InitInfo();  80         }  81   82         private DelegateCommand queryCommand;  83   84         public DelegateCommand QueryCommand  85         {  86             get  87             {  88                 if (queryCommand == null)  89                 {  90                     queryCommand = new DelegateCommand(Query);  91                 }  92                 return queryCommand;  93             }  94         }  95   96         private void Query() {   97             this.pageNum = 1;  98             this.InitInfo();  99         } 100  101         /// <summary> 102         /// 新增命令 103         /// </summary> 104         private DelegateCommand addCommand; 105  106         public DelegateCommand AddCommand 107         { 108             get 109             { 110                 if (addCommand == null) 111                 { 112                     addCommand = new DelegateCommand(Add); 113                 } 114                 return addCommand; 115             } 116         } 117  118         private void Add() 119         { 120             this.dialogService.ShowDialog("addEditClasses",null, AddEditCallBack, "MetroDialogWindow"); 121         } 122  123         private void AddEditCallBack(IDialogResult dialogResult) { 124             if (dialogResult != null && dialogResult.Result == ButtonResult.OK) { 125                 //刷新列表 126                 this.pageNum = 1; 127                 this.InitInfo(); 128             } 129         } 130  131         /// <summary> 132         /// 编辑命令 133         /// </summary> 134         private DelegateCommand<object> editCommand; 135  136         public DelegateCommand<object> EditCommand 137         { 138             get 139             { 140                 if (editCommand == null) 141                 { 142                     editCommand = new DelegateCommand<object>(Edit); 143                 } 144                 return editCommand; 145             } 146         } 147  148         private void Edit(object obj) 149         { 150             if (obj == null) { 151                 return; 152             } 153             var Id = int.Parse(obj.ToString()); 154             var classes = this.Classes.FirstOrDefault(r => r.Id == Id); 155             if (classes == null) 156             { 157                 MessageBox.Show("无效的班级ID"); 158                 return; 159             } 160             if (MessageBoxResult.Yes != MessageBox.Show("Are you sure to delete?", "Confirm", MessageBoxButton.YesNo)) 161             { 162                 return; 163             } 164             IDialogParameters dialogParameters = new DialogParameters(); 165             dialogParameters.Add("classes",classes); 166             this.dialogService.ShowDialog("addEditClasses", dialogParameters, AddEditCallBack, "MetroDialogWindow"); 167         } 168  169         /// <summary> 170         /// 编辑命令 171         /// </summary> 172         private DelegateCommand<object> deleteCommand; 173  174         public DelegateCommand<object> DeleteCommand 175         { 176             get 177             { 178                 if (deleteCommand == null) 179                 { 180                     deleteCommand = new DelegateCommand<object>(Delete); 181                 } 182                 return deleteCommand; 183             } 184         } 185  186         private void Delete(object obj) 187         { 188             if (obj == null) 189             { 190                 return; 191             } 192             var Id = int.Parse(obj.ToString()); 193             var classes = this.Classes.FirstOrDefault(r => r.Id == Id); 194             if (classes == null) 195             { 196                 MessageBox.Show("无效的班级ID"); 197                 return; 198             } 199             bool flag = ClassesHttpUtil.DeleteClasses(Id); 200             if (flag) { 201                 this.pageNum = 1; 202                 this.InitInfo(); 203             } 204         } 205  206         #endregion 207  208     } 209 }

AddEditClassesViewModel代码同样分为三部分:

  1. 属性和构造函数,主要用于数据绑定,如页面文本框,下拉选择框等。
  2. 命令Command,主要用于响应事件,如保存,取消等。
  3. 对话框接口,因为新增编辑是以弹出框的形式呈现,所以根据Prism框架的 要求,需要实现IDialogAware接口。

AddEditClassesViewModel具体代码如下所示:

  1 namespace SIMS.ClassesModule.ViewModels   2 {   3     public class AddEditClassesViewModel : BindableBase, IDialogAware   4     {   5         #region 属性和构造函数   6    7         /// <summary>   8         /// 班级实体   9         /// </summary>  10         private ClassesInfo classes;  11       12         public ClassesInfo Classes  13         {  14             get { return classes; }  15             set { SetProperty(ref classes ,value); }  16         }  17   18         private List<StudentEntity> monitors;  19   20         public List<StudentEntity> Monitors  21         {  22             get { return monitors; }  23             set { SetProperty(ref monitors , value); }  24         }  25   26         private StudentEntity monitor;  27   28         public StudentEntity Monitor  29         {  30             get { return monitor; }  31             set { SetProperty(ref monitor, value); }  32         }  33   34         public AddEditClassesViewModel() {   35           36         }  37   38         #endregion  39   40         #region Command  41   42         private DelegateCommand loadedCommand;  43   44         public DelegateCommand LoadedCommand  45         {  46             get  47             {  48                 if (loadedCommand == null)  49                 {  50                     loadedCommand = new DelegateCommand(Loaded);  51                 }  52                 return loadedCommand;  53             }  54         }  55   56         private void Loaded()  57         {  58             this.Monitors= new List<StudentEntity>();  59             if (Classes?.Id>0) {   60                 var pagedRequst = StudentHttpUtil.GetStudentsByClasses(Classes.Id);  61                 var entities = pagedRequst.items;  62                 Monitors.AddRange(entities);  63                 //如果有班长,则为班长赋值  64                 if (Classes.Monitor > 0) {   65                     this.Monitor= this.Monitors?.FirstOrDefault(r=>r.Id==Classes.Monitor);  66                 }  67             }  68               69         }  70   71         private DelegateCommand cancelCommand;  72   73         public DelegateCommand CancelCommand  74         {  75             get  76             {  77                 if (cancelCommand == null)  78                 {  79                     cancelCommand = new DelegateCommand(Cancel);  80                 }  81                 return cancelCommand;  82             }  83         }  84   85         private void Cancel()  86         {  87             RequestClose?.Invoke((new DialogResult(ButtonResult.Cancel)));  88         }  89   90         private DelegateCommand  saveCommand;  91   92         public DelegateCommand SaveCommand  93         {  94             get  95             {  96                 if (saveCommand == null)  97                 {  98                     saveCommand = new DelegateCommand(Save);  99                 } 100                 return saveCommand; 101             } 102         } 103  104         private void Save() { 105             if (Classes != null) { 106                 Classes.CreateTime = DateTime.Now; 107                 Classes.LastEditTime = DateTime.Now; 108                 if (Monitor != null) { 109                     Classes.Monitor = Monitor.Id; 110                 } 111                 bool flag=false; 112                 if (Classes.Id > 0) { 113                    flag = ClassesHttpUtil.UpdateClasses(Classes); 114                 } 115                 else {  116                    flag = ClassesHttpUtil.AddClasses(Classes); 117                 } 118                 if (flag) 119                 { 120                     RequestClose?.Invoke((new DialogResult(ButtonResult.OK))); 121                 } 122             } 123         } 124  125  126         #endregion 127  128         #region 对话框 129  130         public string Title =>  "新增或编辑班级信息"; 131  132         public event Action<IDialogResult> RequestClose; 133  134         public bool CanCloseDialog() 135         { 136             return true; 137         } 138  139         public void OnDialogClosed() 140         { 141              142         } 143  144         public void OnDialogOpened(IDialogParameters parameters) 145         { 146             if (parameters != null && parameters.ContainsKey("classes")) 147             { 148                 this.Classes = parameters.GetValue<ClassesInfo>("classes"); 149             } 150             else {  151                 this.Classes = new ClassesInfo(); 152             } 153         } 154  155         #endregion 156  157     } 158 }

4. 示例截图

班级管理示例截图,如下所示:

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

 

学生管理

1. 接口访问类StudentHttpUtil

学生数据表结构和服务接口,在第二篇文章中已有介绍,如有疑问,可前往参考。接口访问类用于封装访问服务端提供的接口。如下所示:

 1 namespace SIMS.Utils.Http  2 {  3     /// <summary>  4     /// 学生类Http访问通用类  5     /// </summary>  6     public class StudentHttpUtil:HttpUtil  7     {  8         /// <summary>  9         /// 通过id查询学生信息 10         /// </summary> 11         /// <param name="id"></param> 12         /// <returns></returns> 13         public static StudentEntity GetStudent(int id) 14         { 15             Dictionary<string, object> data = new Dictionary<string, object>(); 16             data["id"] = id; 17             var str = Get(UrlConfig.STUDENT_GETSTUDENT, data); 18             var student = StrToObject<StudentEntity>(str); 19             return student; 20         } 21  22         public static PagedRequest<StudentEntity> GetStudents(string no,string name, int pageNum, int pageSize) { 23             Dictionary<string, object> data = new Dictionary<string, object>(); 24             data["no"] = no; 25             data["name"] = name; 26             data["pageNum"] = pageNum; 27             data["pageSize"] = pageSize; 28             var str = Get(UrlConfig.STUDENT_GETSTUDENTS, data); 29             var students = StrToObject<PagedRequest<StudentEntity>>(str); 30             return students; 31         } 32  33         public static PagedRequest<StudentEntity> GetStudentsByClasses(int classId) 34         { 35             Dictionary<string, object> data = new Dictionary<string, object>(); 36             data["classId"] = classId; 37             var str = Get(UrlConfig.STUDENT_GETSTUDENTSBYCLASSES, data); 38             var students = StrToObject<PagedRequest<StudentEntity>>(str); 39             return students; 40         } 41  42         public static bool AddStudent(StudentEntity student) 43         { 44             var ret = Post<StudentEntity>(UrlConfig.STUDENT_ADDSTUDENT, student); 45             return int.Parse(ret) == 0; 46         } 47  48         public static bool UpdateStudent(StudentEntity student) 49         { 50             var ret = Put<StudentEntity>(UrlConfig.STUDENT_UPDATESTUDENT, student); 51             return int.Parse(ret) == 0; 52         } 53  54         public static bool DeleteStudent(int Id) 55         { 56             Dictionary<string, string> data = new Dictionary<string, string>(); 57             data["Id"] = Id.ToString(); 58             var ret = Delete(UrlConfig.STUDENT_DELETESTUDENT, data); 59             return int.Parse(ret) == 0; 60         } 61     } 62 }

2. 客户端页面视图

学生管理模块的客户端视图页面,也分为两个:学生列表查询,新增编辑学生信息页面。

学生列表查询页面

学生信息列表页面设计知识点,和班级管理差不多,只有一点差异:

  1. 在数据库中,性别保存的是bit类型,在C#中,数据类型为bool,但是在列表中需要转换成男或女显示,所以需要用到Converter进行转换。

学生信息查询页面,具体代码如下所示:

  1 <UserControl x:Class="SIMS.StudentModule.Views.Student"   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.StudentModule.Views"   7       xmlns:i="http://schemas.microsoft.com/xaml/behaviors"   8       xmlns:mahApps ="http://metro.mahapps.com/winfx/xaml/controls"   9       xmlns:prism="http://prismlibrary.com/"        10       xmlns:ctrls ="clr-namespace:SIMS.Utils.Controls;assembly=SIMS.Utils"  11       xmlns:conv="clr-namespace:SIMS.Utils.Converter;assembly=SIMS.Utils"  12       mc:Ignorable="d"   13       prism:ViewModelLocator.AutoWireViewModel="True"  14       d:DesignHeight="450" d:DesignWidth="800">  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/Themes/Light.Blue.xaml" />  21                 <ResourceDictionary>  22                     <conv:SexConverter x:Key="SexConverter"></conv:SexConverter>  23                     <Style x:Key="LinkButton" TargetType="Button">  24                         <Setter Property="Background" Value="White"></Setter>  25                         <Setter Property="Cursor" Value="Hand"></Setter>  26                         <Setter Property="Margin" Value="3"></Setter>  27                         <Setter Property="MinWidth" Value="80"></Setter>  28                         <Setter Property="MinHeight" Value="25"></Setter>  29                         <Setter Property="BorderThickness" Value="0 0 0 0"></Setter>  30                     </Style>  31                 </ResourceDictionary>  32             </ResourceDictionary.MergedDictionaries>  33         </ResourceDictionary>  34     </UserControl.Resources>  35     <i:Interaction.Triggers>  36         <i:EventTrigger EventName="Loaded">  37             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction>  38         </i:EventTrigger>  39     </i:Interaction.Triggers>  40     <Grid>  41         <Grid.RowDefinitions>  42             <RowDefinition Height="Auto"></RowDefinition>  43             <RowDefinition Height="Auto"></RowDefinition>  44             <RowDefinition Height="*"></RowDefinition>  45             <RowDefinition Height="Auto"></RowDefinition>  46         </Grid.RowDefinitions>  47         <TextBlock Text="学生信息" FontSize="20" Background="AliceBlue" Margin="2"></TextBlock>  48         <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center">  49             <TextBlock Text="学号" VerticalAlignment="Center" Margin="2"></TextBlock>  50             <TextBox Margin="4" MinWidth="120" Height="30"  51                      Text="{Binding No}"  52                              HorizontalContentAlignment="Stretch"  53                              mahApps:TextBoxHelper.ClearTextButton="True"  54                              mahApps:TextBoxHelper.Watermark="学号"  55                              mahApps:TextBoxHelper.WatermarkAlignment="Left"  56                              SpellCheck.IsEnabled="True" />  57             <TextBlock Text="姓名" VerticalAlignment="Center" Margin="2"></TextBlock>  58             <TextBox Margin="4" MinWidth="120" Height="30"  59                      Text="{Binding Name}"  60                              HorizontalContentAlignment="Stretch"  61                              mahApps:TextBoxHelper.ClearTextButton="True"  62                              mahApps:TextBoxHelper.Watermark="学生姓名"  63                              mahApps:TextBoxHelper.WatermarkAlignment="Left"  64                              SpellCheck.IsEnabled="True" />  65             <Button Content="查询" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Width="120" Height="30" Margin="3" Command="{Binding QueryCommand}"></Button>  66             <Button Content="新增" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Width="120" Height="30" Margin="3" Command="{Binding AddCommand}"></Button>  67         </StackPanel>  68         <DataGrid x:Name="dgStudent"  69                   Grid.Row="2"  70                   Grid.Column="0"  71                   Margin="2"  72                   AutoGenerateColumns="False"  73                   CanUserAddRows="False"  74                   CanUserDeleteRows="False"  75                   ItemsSource="{Binding Students}"  76                   RowHeaderWidth="0">  77             <DataGrid.Columns>  78                 <DataGridTextColumn Binding="{Binding No}" Header="学号" Width="*" />  79                 <DataGridTextColumn Binding="{Binding Name}" Header="姓名" Width="*"/>  80                 <DataGridTextColumn Binding="{Binding Age}" Header="年龄" Width="*"/>  81                 <DataGridTextColumn Binding="{Binding Sex, Converter={StaticResource SexConverter}}" Header="性别" Width="*"/>  82                 <DataGridTextColumn Binding="{Binding ClassesName}" Header="班级" Width="*" />  83                 <DataGridTemplateColumn Header="操作" Width="*">  84                     <DataGridTemplateColumn.CellTemplate>  85                         <DataTemplate>  86                             <StackPanel Orientation="Horizontal">  87                                 <Button Content="Edit" Style="{StaticResource LinkButton}" Command="{Binding RelativeSource={RelativeSource  AncestorType=DataGrid,  Mode=FindAncestor}, Path=DataContext.EditCommand}" CommandParameter="{Binding Id}"  >  88                                     <Button.Template>  89                                         <ControlTemplate TargetType="Button">  90                                             <TextBlock TextDecorations="Underline" HorizontalAlignment="Center">  91                                                 <ContentPresenter />  92                                             </TextBlock>  93                                         </ControlTemplate>  94                                     </Button.Template>  95                                 </Button>  96                                 <Button Content="Delete" Style="{StaticResource LinkButton}" Command="{Binding RelativeSource={RelativeSource  AncestorType=DataGrid,  Mode=FindAncestor}, Path=DataContext.DeleteCommand}" CommandParameter="{Binding Id}">  97                                     <Button.Template>  98                                         <ControlTemplate TargetType="Button">  99                                             <TextBlock TextDecorations="Underline" HorizontalAlignment="Center"> 100                                                 <ContentPresenter /> 101                                             </TextBlock> 102                                         </ControlTemplate> 103                                     </Button.Template> 104                                 </Button> 105                             </StackPanel> 106                         </DataTemplate> 107                     </DataGridTemplateColumn.CellTemplate> 108                 </DataGridTemplateColumn> 109             </DataGrid.Columns> 110         </DataGrid> 111         <ctrls:PageControl Grid.Row="3" DataContext="{Binding}" ></ctrls:PageControl> 112     </Grid> 113 </UserControl>

新增编辑页面

新增编辑页面涉及知识点和班级新增页面差不多,仅有一处差异:

  1. C#中的bool类型,需要绑定到两个单选按钮上,以表示男,女,所以需要扩展。

新增编辑页面,具体代码如下所示:

 1 <UserControl x:Class="SIMS.StudentModule.Views.AddEditStudent"  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.StudentModule.Views"  7              xmlns:i="http://schemas.microsoft.com/xaml/behaviors"  8              xmlns:mahApps ="http://metro.mahapps.com/winfx/xaml/controls"  9              xmlns:prism="http://prismlibrary.com/"       10              mc:Ignorable="d"  11              d:DesignHeight="450" d:DesignWidth="600"> 12     <prism:Dialog.WindowStyle> 13         <Style TargetType="Window"> 14             <Setter Property="Width" Value="600"></Setter> 15             <Setter Property="Height" Value="400"></Setter> 16         </Style> 17     </prism:Dialog.WindowStyle> 18     <UserControl.Resources> 19         <ResourceDictionary> 20             <ResourceDictionary.MergedDictionaries> 21                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> 22                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" /> 23             </ResourceDictionary.MergedDictionaries> 24         </ResourceDictionary> 25     </UserControl.Resources> 26     <i:Interaction.Triggers> 27         <i:EventTrigger EventName="Loaded"> 28             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction> 29         </i:EventTrigger> 30     </i:Interaction.Triggers> 31     <Grid> 32         <Grid.ColumnDefinitions> 33             <ColumnDefinition Width="0.2*"></ColumnDefinition> 34             <ColumnDefinition Width="Auto"></ColumnDefinition> 35             <ColumnDefinition Width="*"></ColumnDefinition> 36             <ColumnDefinition Width="0.2*"></ColumnDefinition> 37         </Grid.ColumnDefinitions> 38         <Grid.RowDefinitions> 39             <RowDefinition></RowDefinition> 40             <RowDefinition></RowDefinition> 41             <RowDefinition></RowDefinition> 42             <RowDefinition></RowDefinition> 43             <RowDefinition></RowDefinition> 44             <RowDefinition></RowDefinition> 45         </Grid.RowDefinitions> 46  47  48         <TextBlock Text="学号" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" Margin="3"></TextBlock> 49         <TextBox Grid.Row="0" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Student.No}"></TextBox> 50         <TextBlock Text="姓名" Grid.Row="1" Grid.Column="1"  VerticalAlignment="Center" Margin="3"></TextBlock> 51         <TextBox Grid.Row="1" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Student.Name}"></TextBox> 52         <TextBlock Text="年龄" Grid.Row="2" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 53         <TextBox Grid.Row="2" Grid.Column="2" MinWidth="120" Height="35"   VerticalAlignment="Center" Margin="3" Text="{Binding Student.Age}"></TextBox> 54         <TextBlock Text="性别" Grid.Row="3" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 55         <StackPanel Grid.Row="3" Grid.Column="2" Orientation="Horizontal" > 56             <RadioButton Content="男" IsChecked="{Binding Student.IsBoy}"></RadioButton> 57             <RadioButton Content="女" IsChecked="{Binding Student.IsGirl}"></RadioButton> 58         </StackPanel> 59          60         <TextBlock Text="班级" Grid.Row="4" Grid.Column="1"   VerticalAlignment="Center" Margin="3"></TextBlock> 61         <ComboBox Grid.Row="4" Grid.Column="2" MinWidth="120" Height="35" ItemsSource="{Binding Classess}" mahApps:TextBoxHelper.ClearTextButton="True" SelectedItem="{Binding Classes}"> 62             <ComboBox.ItemTemplate> 63                 <DataTemplate> 64                     <StackPanel Orientation="Horizontal"> 65                         <TextBlock Text="{Binding Dept}"></TextBlock> 66                         <TextBlock Text="{Binding Grade}"></TextBlock> 67                         <TextBlock Text="{Binding Name}"></TextBlock> 68                     </StackPanel> 69                 </DataTemplate> 70             </ComboBox.ItemTemplate> 71         </ComboBox> 72         <StackPanel Grid.Row="5" Grid.Column="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center" Margin="3"> 73             <Button Content="取消" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding CancelCommand}" ></Button> 74             <Button Content="保存" Margin="5" MinWidth="120" Height="35" Style="{DynamicResource MahApps.Styles.Button.Square.Accent}" Command="{Binding SaveCommand}"></Button> 75         </StackPanel> 76     </Grid> 77 </UserControl>

3. 客户端ViewModel

学生管理客户端ViewModel,与页面视图对应,也分为两个部分

StudentViewModel代码分为三部分:

  1. 属性和构造函数,主要用于数据绑定,如查询条件,列表等。所有属性的set赋值时,均采用SetProperty进行赋值。
  2. 命令Command,如查询,新增,编辑,删除命令等。所有命令可以定义成DelegateCommand类型。
  3. 分页部分,因分页功能代码大同小异,所以此处略去。

StudentViewModel具体代码如下所示:

  1 namespace SIMS.StudentModule.ViewModels   2 {   3     public class StudentViewModel:BindableBase   4     {   5         #region 属性及构造函数   6    7         /// <summary>   8         /// 学号   9         /// </summary>  10         private string no;  11   12         public string No  13         {  14             get { return no; }  15             set { SetProperty(ref no , value); }  16         }  17   18         /// <summary>  19         /// 学生姓名  20         /// </summary>  21         private string name;  22   23         public string Name  24         {  25             get { return name; }  26             set { SetProperty(ref name, value); }  27         }  28   29         private ObservableCollection<StudentInfo> students;  30   31         public ObservableCollection<StudentInfo> Students  32         {  33             get { return students; }  34             set { SetProperty(ref students, value); }  35         }  36   37         private IDialogService dialogService;  38   39         public StudentViewModel(IDialogService dialogService) {  40             this.dialogService = dialogService;  41             this.pageNum = 1;  42             this.pageSize = 20;  43         }  44   45         private void InitInfo() {  46             Students = new ObservableCollection<StudentInfo>();  47             var pagedRequst = StudentHttpUtil.GetStudents(this.No,this.Name, this.pageNum, this.pageSize);  48             var entities = pagedRequst.items;  49             Students.AddRange(entities.Select(r=>new StudentInfo(r)));  50             //  51             this.TotalCount = pagedRequst.count;  52             this.TotalPage=((int)Math.Ceiling(this.TotalCount*1.0/this.pageSize));  53         }  54   55         #endregion  56   57         #region 事件  58   59         private DelegateCommand loadedCommand;  60   61         public DelegateCommand LoadedCommand  62         {  63             get  64             {  65                 if (loadedCommand == null)  66                 {  67                     loadedCommand = new DelegateCommand(Loaded);  68                 }  69                 return loadedCommand;  70             }  71         }  72   73         private void Loaded()  74         {  75             InitInfo();  76         }  77   78         /// <summary>  79         /// 新增命令  80         /// </summary>  81         private DelegateCommand addCommand;  82   83         public DelegateCommand AddCommand  84         {  85             get  86             {  87                 if (addCommand == null)  88                 {  89                     addCommand = new DelegateCommand(Add);  90                 }  91                 return addCommand;  92             }  93         }  94   95         private void Add()  96         {  97             this.dialogService.ShowDialog("addEditStudent", null, AddEditCallBack, "MetroDialogWindow");  98         }  99  100         private void AddEditCallBack(IDialogResult dialogResult) 101         { 102             if (dialogResult != null && dialogResult.Result == ButtonResult.OK) 103             { 104                 //刷新列表 105                 this.pageNum = 1; 106                 this.InitInfo(); 107             } 108         } 109  110         /// <summary> 111         /// 编辑命令 112         /// </summary> 113         private DelegateCommand<object> editCommand; 114  115         public DelegateCommand<object> EditCommand 116         { 117             get 118             { 119                 if (editCommand == null) 120                 { 121                     editCommand = new DelegateCommand<object>(Edit); 122                 } 123                 return editCommand; 124             } 125         } 126  127         private void Edit(object obj) { 128             if (obj == null) 129             { 130                 return; 131             } 132             var Id = int.Parse(obj.ToString()); 133             var student = this.Students.FirstOrDefault(r => r.Id == Id); 134             if (student == null) 135             { 136                 MessageBox.Show("无效的学生ID"); 137                 return; 138             } 139             if (MessageBoxResult.Yes != MessageBox.Show("Are you sure to delete?", "Confirm", MessageBoxButton.YesNo)) 140             { 141                 return; 142             } 143             IDialogParameters dialogParameters = new DialogParameters(); 144             dialogParameters.Add("student", student); 145             this.dialogService.ShowDialog("addEditStudent", dialogParameters, AddEditCallBack, "MetroDialogWindow"); 146         } 147  148         /// <summary> 149         /// 编辑命令 150         /// </summary> 151         private DelegateCommand<object> deleteCommand; 152  153         public DelegateCommand<object> DeleteCommand 154         { 155             get 156             { 157                 if (deleteCommand == null) 158                 { 159                     deleteCommand = new DelegateCommand<object>(Delete); 160                 } 161                 return deleteCommand; 162             } 163         } 164  165         private void Delete(object obj) 166         { 167             if (obj == null) 168             { 169                 return; 170             } 171             var Id = int.Parse(obj.ToString()); 172             var classes = this.Students.FirstOrDefault(r => r.Id == Id); 173             if (classes == null) 174             { 175                 MessageBox.Show("无效的学生ID"); 176                 return; 177             } 178             bool flag = StudentHttpUtil.DeleteStudent(Id); 179             if (flag) 180             { 181                 this.pageNum = 1; 182                 this.InitInfo(); 183             } 184         } 185  186         #endregion 187  188     } 189 }

AddEditStudentViewModel代码同样分为三部分:

  1. 属性和构造函数,主要用于数据绑定,如页面文本框,下拉选择框等。
  2. 命令Command,主要用于响应事件,如保存,取消等。
  3. 对话框接口,因为新增编辑是以弹出框的形式呈现,所以根据Prism框架的 要求,需要实现IDialogAware接口。(实现接口代码大同小异,在此略去)

AddEditStudentViewModel具体代码如下所示:

  1 namespace SIMS.StudentModule.ViewModels   2 {   3     public class AddEditStudentViewModel : BindableBase, IDialogAware   4     {   5    6         /// <summary>   7         /// 班级实体   8         /// </summary>   9         private ClassesEntity classes;  10   11         public ClassesEntity Classes  12         {  13             get { return classes; }  14             set { SetProperty(ref classes, value); }  15         }  16   17         /// <summary>  18         /// 班级列表  19         /// </summary>  20         private List<ClassesEntity> classess;  21   22         public List<ClassesEntity> Classess  23         {  24             get { return classess; }  25             set { SetProperty(ref classess, value); }  26         }  27   28         private StudentInfo student;  29   30         public StudentInfo Student  31         {  32             get { return student; }  33             set { student = value; }  34         }  35   36         public AddEditStudentViewModel() {   37           38         }  39   40         #region Command  41   42         private DelegateCommand loadedCommand;  43   44         public DelegateCommand LoadedCommand  45         {  46             get  47             {  48                 if (loadedCommand == null)  49                 {  50                     loadedCommand = new DelegateCommand(Loaded);  51                 }  52                 return loadedCommand;  53             }  54         }  55   56         private void Loaded()  57         {  58             this.Classess = new List<ClassesEntity>();  59             var pagedRequst = ClassesHttpUtil.GetClassess(null,null,1,0);//0表示所有班级  60             var entities = pagedRequst.items;  61             Classess.AddRange(entities);  62         }  63   64         private DelegateCommand cancelCommand;  65   66         public DelegateCommand CancelCommand  67         {  68             get  69             {  70                 if (cancelCommand == null)  71                 {  72                     cancelCommand = new DelegateCommand(Cancel);  73                 }  74                 return cancelCommand;  75             }  76         }  77   78         private void Cancel() {  79             RequestClose?.Invoke((new DialogResult(ButtonResult.Cancel)));  80         }  81   82         private DelegateCommand saveCommand;  83   84         public DelegateCommand SaveCommand  85         {  86             get  87             {  88                 if (saveCommand == null)  89                 {  90                     saveCommand = new DelegateCommand(Save);  91                 }  92                 return saveCommand;  93             }  94         }  95   96         private void Save()  97         {  98             if (Student != null)  99             { 100                 Student.CreateTime = DateTime.Now; 101                 Student.LastEditTime = DateTime.Now; 102                 bool flag = false; 103                 if (Classes != null) {  104                     Student.ClassesId = Classes.Id; 105                 } 106                 if (Student.Id > 0) 107                 { 108                     flag = StudentHttpUtil.UpdateStudent(Student); 109                 } 110                 else 111                 { 112                     flag = StudentHttpUtil.AddStudent(Student); 113                 } 114                 if (flag) 115                 { 116                     RequestClose?.Invoke((new DialogResult(ButtonResult.OK))); 117                 } 118             } 119         } 120  121         #endregion 122     } 123 }

4. 示例截图

学生管理示例截图,如下所示:

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

总结

通过本篇文章的班级管理模块,学生管理模块,以及上一篇文章中的课程管理模块,不难发现,每一个模块的开发都是由列表DataGrid,文本框TextBox,下拉框Combox,单选按钮RadioButton,按钮Button等组成的,虽功能略有差异,但总归万变不离其宗。开发方法也大同小异,复杂的功能都是普通的功能累加起来的。这也是本系列文章由浅入深的渐进安排。希望能够抛砖引玉,不局限于某一功能,而是能够举一反三,自我理解,以达到自我开发的能力。