最近通過WPF開發項目,為了對WPF知識點進行總結,所以利用業餘時間,開發一個學生信息管理系統【Student Information Management System】。前三篇文章進行了框架搭建和模塊劃分,後臺WebApi介面編寫,以及課程管理模塊開發,本文在前三篇基礎之上,繼續深入開發學生信息... ...
最近通過WPF開發項目,為了對WPF知識點進行總結,所以利用業餘時間,開發一個學生信息管理系統【Student Information Management System】。前三篇文章進行了框架搭建和模塊劃分,後臺WebApi介面編寫,以及課程管理模塊開發,本文在前三篇基礎之上,繼續深入開發學生信息管理系統的班級管理和學生管理模塊,通過本篇文章,將繼續鞏固之前的知識點,本文僅供學習分享使用,如有不足之處,還請指正。
涉及知識點
由於班級管理和學生管理的服務端開發,在第二篇文章中以後介紹,所以本篇專註介紹客戶端功能的開發。涉及知識點如下:
- WPF開發中TextBlock,TextBox,DataGrid,Combox等控制項的基礎使用以及數據綁定等操作。
- MAH樣式的使用,在本示例中MAH主要用於統一頁面風格,提高用戶體驗。
- HttpClient使用,主要用於訪問服務端提供的介面。
業務邏輯
首先班級管理和學生管理既有關聯,又相互獨立,不像課程管理模塊獨立存在,不與其他模塊存在依賴。所以兩個模塊一起放在一篇文章進行講解。關係如下:
- 學生屬於某一班級之學生,所以學生中包含班級信息。
- 班級中存在班長,班長又屬於學生的一個實體。
班級管理
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. 客戶端頁面視圖
班級管理的客戶端頁面視圖共兩個,一個查詢列表頁面,一個新增編輯頁面,共同組成了班級管理的增刪改查。
查詢班級列表頁面,涉及知識點如下所示:
- 查詢條件或者列表中數據列展示,通過數據綁定Binding的方式與ViewModel進行交互,即點擊查詢按鈕,不再傳遞參數,因為ViewModel中的屬性已經同步更新。
- ViewModel中並非所有屬性都可實現雙向綁定,必須是實現具有通知功能的屬性才可以。在Prism框架中,通過BindableBase的SetProperty方法可以快速實現。
- View視圖中如果控制項存在Command命令,則可以直接綁定,如果不存在,則可以i:Interaction.Triggers將事件轉換為命令,如Load事件等。
- 在列表中,如果需要添加按鈕,可以通過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>
新增編輯頁面
班級的新增功能和編輯功能,共用一個頁面,涉及知識點如下所示:
- 在新增編輯的ViewModel中,班級實體是一個屬性,所以在視圖控制項中進行數據綁定時,需要帶上屬性名,如:Classes.Name 。
- 班長列表在新增班級時尚無對應學生,可為空,待維護學生後,可通過學生列表進行選擇即可。
- 班長列表為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>