WPF開發學生信息管理系統【WPF+Prism+MAH+WebApi】(完)

来源:https://www.cnblogs.com/hsiang/archive/2022/06/05/16344601.html
-Advertisement-
Play Games

最近通過WPF開發項目,為了對WPF知識點進行總結,所以利用業餘時間,開發一個學生信息管理系統【Student Information Management System】。前四篇文章進行了框架搭建和模塊劃分,後臺WebApi介面編寫,以及課程管理模塊,班級管理模塊,學生管理模塊的開發,本文在前四篇... ...


最近通過WPF開發項目,為了對WPF知識點進行總結,所以利用業餘時間,開發一個學生信息管理系統【Student Information Management System】。前四篇文章進行了框架搭建和模塊劃分,後臺WebApi介面編寫,以及課程管理模塊,班級管理模塊,學生管理模塊的開發,本文在前四篇基礎之上,繼續深入開發學生信息管理系統的成績管理和系統管理模塊,通過本篇文章,將繼續鞏固之前的知識點,本文僅供學習分享使用,如有不足之處,還請指正。

涉及知識點

學生信息管理系統SIMS屬於一個小型的完整系統開發,涉及的知識點比較,具體如下所示:

  1. WPF開發中TextBlock,TextBox,DataGrid,Combox,TabControl等控制項的基礎使用以及數據綁定等操作。
  2. MAH樣式的使用,在本示例中MAH主要用於統一頁面風格,提高用戶體驗。
  3. HttpClient使用,主要用於訪問服務端提供的介面。

業務邏輯

前面幾篇文章,由淺入深,逐步介紹了課程管理模塊,班級管理模塊,學生管理模塊,今天繼續介紹成績管理模塊,業務邏輯關係如下:

  1. 學生屬於某一班級之學生,所以學生中包含班級信息。
  2. 班級中存在班長,同時班長又屬於學生的一個實體。
  3. 成績是某一學生的成績,且一名學生有各門課程的成績。所以成績和學生有關,且和課程有關。

實體E-R圖

學生表,成績表,班級表,課程表,各個數據表之間的E-R圖,如下所示:

由此可見,成績表與課程和學生表,都有關聯,所以放在最後。

成績管理

成績管理主要用於錄入各個學生各個課程的成績,包含成績表的增刪改查功能。

1. 成績管理後臺服務Service

IScoreAppService介面是對成績管理的抽象,如下所示:

 1 namespace SIMS.WebApi.Services.Score
 2 {
 3     public interface IScoreAppService
 4     {
 5         public PagedRequest<ScoreEntity> GetScores(string studentName,string courseName,int pageNum,int pageSize);
 6 
 7         /// <summary>
 8         /// 通過id查詢成績信息
 9         /// </summary>
10         /// <param name="id"></param>
11         /// <returns></returns>
12         public ScoreEntity GetScore(int id);
13 
14         /// <summary>
15         /// 新增成績
16         /// </summary>
17         /// <param name="score"></param>
18         /// <returns></returns>
19         public int AddScore(ScoreEntity score);
20 
21         /// <summary>
22         /// 修改成績
23         /// </summary>
24         /// <param name="score"></param>
25         /// <returns></returns>
26         public int UpdateScore(ScoreEntity score);
27 
28         /// <summary>
29         /// 刪除成績
30         /// </summary>
31         /// <param name="id"></param>
32         public int DeleteScore(int id);
33     }
34 }

服務實現類ScoreAppService,是對介面的實現,具體如下所示:

 1 namespace SIMS.WebApi.Services.Score
 2 {
 3     public class ScoreAppService : IScoreAppService
 4     {
 5         private DataContext dataContext;
 6 
 7         public ScoreAppService(DataContext dataContext)
 8         {
 9             this.dataContext = dataContext;
10         }
11 
12         public int AddScore(ScoreEntity score)
13         {
14             var entity = this.dataContext.Scores.Add(score);
15             this.dataContext.SaveChanges();
16             return 0;
17         }
18 
19         public int DeleteScore(int id)
20         {
21             var entity = dataContext.Scores.FirstOrDefault(x => x.Id == id);
22             if (entity != null)
23             {
24                 dataContext.Scores.Remove(entity);
25                 dataContext.SaveChanges();
26             }
27             return 0;
28         }
29 
30         public ScoreEntity GetScore(int id)
31         {
32             var entity = dataContext.Scores.FirstOrDefault(r => r.Id == id);
33             return entity;
34         }
35 
36         /// <summary>
37         /// 按條件查詢成績列表
38         /// </summary>
39         /// <param name="studentName"></param>
40         /// <param name="courseName"></param>
41         /// <param name="pageNum"></param>
42         /// <param name="pageSize"></param>
43         /// <returns></returns>
44         public PagedRequest<ScoreEntity> GetScores(string studentName, string courseName, int pageNum, int pageSize)
45         {
46             IQueryable<ScoreEntity> scores = null;
47             if (!string.IsNullOrEmpty(studentName) && !string.IsNullOrEmpty(courseName))
48             {
49                 var students = this.dataContext.Students.Where(r => r.Name.Contains(studentName));
50                 var courses = this.dataContext.Courses.Where(r => r.Name.Contains(courseName));
51                 scores = this.dataContext.Scores.Where(r => students.Select(t => t.Id).Contains(r.StudentId)).Where(r => courses.Select(t => t.Id).Contains(r.CourseId));
52             }
53             else if (!string.IsNullOrEmpty(studentName))
54             {
55                 var students = this.dataContext.Students.Where(r => r.Name.Contains(studentName));
56                 scores = this.dataContext.Scores.Where(r => students.Select(t => t.Id).Contains(r.StudentId));
57             }
58             else if (!string.IsNullOrEmpty(courseName))
59             {
60                 var courses = this.dataContext.Courses.Where(r => r.Name.Contains(courseName));
61                 scores = this.dataContext.Scores.Where(r => courses.Select(t => t.Id).Contains(r.CourseId));
62             }
63             else {
64                 scores = dataContext.Scores.Where(r => true).OrderBy(r => r.Id);
65             }
66             int count = scores.Count();
67             List<ScoreEntity> items;
68             if (pageSize > 0)
69             {
70                 items = scores.Skip((pageNum - 1) * pageSize).Take(pageSize).ToList();
71             }
72             else
73             {
74                 items = scores.ToList();
75             }
76             return new PagedRequest<ScoreEntity>()
77             {
78                 count = count,
79                 items = items
80             };
81         }
82 
83         public int UpdateScore(ScoreEntity score)
84         {
85             dataContext.Scores.Update(score);
86             dataContext.SaveChanges();
87             return 0;
88         }
89     }
90 }

2. 成績管理WebApi介面控制器

控制器是對數據服務的公開,每一個控制器的方法表示一個Action,即表示一個客戶端可以訪問的入口。具體如下所示:

 1 namespace SIMS.WebApi.Controllers
 2 {
 3     /// <summary>
 4     /// 成績控制器
 5     /// </summary>
 6     [Route("api/[controller]/[action]")]
 7     [ApiController]
 8     public class ScoreController : ControllerBase
 9     {
10         private readonly ILogger<ScoreController> logger;
11 
12         private readonly IScoreAppService scoreAppService;
13 
14         public ScoreController(ILogger<ScoreController> logger, IScoreAppService scoreAppService)
15         {
16             this.logger = logger;
17             this.scoreAppService = scoreAppService;
18         }
19 
20         /// <summary>
21         /// 獲取成績信息
22         /// </summary>
23         /// <param name="id"></param>
24         /// <returns></returns>
25         [HttpGet]
26         public PagedRequest<ScoreEntity> GetScores(string? studentName, string? courseName, int pageNum, int pageSize)
27         {
28             return scoreAppService.GetScores(studentName, courseName, pageNum, pageSize);
29         }
30 
31         /// <summary>
32         /// 獲取成績信息
33         /// </summary>
34         /// <param name="id"></param>
35         /// <returns></returns>
36         [HttpGet]
37         public ScoreEntity GetScore(int id)
38         {
39             return scoreAppService.GetScore(id);
40         }
41 
42         /// <summary>
43         /// 新增成績
44         /// </summary>
45         /// <param name="score"></param>
46         /// <returns></returns>
47         [HttpPost]
48         public int AddScore(ScoreEntity score)
49         {
50             return scoreAppService.AddScore(score);
51         }
52 
53         /// <summary>
54         /// 修改成績
55         /// </summary>
56         /// <param name="score"></param>
57         /// <returns></returns>
58         [HttpPut]
59         public int UpdateScore(ScoreEntity score)
60         {
61             return scoreAppService.UpdateScore(score);
62         }
63 
64         /// <summary>
65         /// 刪除成績
66         /// </summary>
67         /// <param name="id"></param>
68         [HttpDelete]
69         public int DeleteScore(int id)
70         {
71             return scoreAppService.DeleteScore(id);
72         }
73     }
74 }

當服務運行起來後,Swagger還每一個控制器都進行歸類,可以清晰的看到每一個介面對應的網址,成績管理模塊對應的介面如下所示:

 

 

3. 成績管理客戶端介面訪問類HttpUtil

在學生信息系統開發的過程中,發現所有的介面訪問都是通用的,所以對介面訪問功能提取成一個HttpUtil基類【包括GET,POST,PUT,DELETE等功能】,其他具體業務再繼承基類,並細化具體業務即可。ScoreHttpUtil代碼如下所示:

 1 namespace SIMS.Utils.Http
 2 {
 3     public class ScoreHttpUtil:HttpUtil
 4     {
 5         /// <summary>
 6         /// 通過id查詢成績信息
 7         /// </summary>
 8         /// <param name="id"></param>
 9         /// <returns></returns>
10         public static ScoreEntity GetScore(int id)
11         {
12             Dictionary<string, object> data = new Dictionary<string, object>();
13             data["id"] = id;
14             var str = Get(UrlConfig.SCORE_GETSCORE, data);
15             var socre = StrToObject<ScoreEntity>(str);
16             return socre;
17         }
18 
19         /// <summary>
20         /// 
21         /// </summary>
22         /// <param name="studentName"></param>
23         /// <param name="courseName"></param>
24         /// <param name="pageNum"></param>
25         /// <param name="pageSize"></param>
26         /// <returns></returns>
27         public static PagedRequest<ScoreEntity> GetScores(string? studentName, string? courseName, int pageNum, int pageSize)
28         {
29             Dictionary<string, object> data = new Dictionary<string, object>();
30             data["courseName"] = courseName;
31             data["studentName"] = studentName;
32             data["pageNum"] = pageNum;
33             data["pageSize"] = pageSize;
34             var str = Get(UrlConfig.SCORE_GETSCORES, data);
35             var socres = StrToObject<PagedRequest<ScoreEntity>>(str);
36             return socres;
37         }
38 
39         public static bool AddScore(ScoreEntity socre)
40         {
41             var ret = Post<ScoreEntity>(UrlConfig.SCORE_ADDSCORE, socre);
42             return int.Parse(ret) == 0;
43         }
44 
45         public static bool UpdateScore(ScoreEntity socre)
46         {
47             var ret = Put<ScoreEntity>(UrlConfig.SCORE_UPDATESCORE, socre);
48             return int.Parse(ret) == 0;
49         }
50 
51         public static bool DeleteScore(int Id)
52         {
53             Dictionary<string, string> data = new Dictionary<string, string>();
54             data["Id"] = Id.ToString();
55             var ret = Delete(UrlConfig.SCORE_DELETESCORE, data);
56             return int.Parse(ret) == 0;
57         }
58     }
59 }

4. 成績管理客戶端操作

經過前面四個部分的開發,客戶端就可以與數據介面進行交互,展示數據到客戶端。客戶端所有的開發,均採用MVVM模式進行。

在成績管理模塊中,根據功能區分,主要包含兩個View視圖及對應的ViewModel。如下所示:

  1. Score視圖,主要用於成績的查詢,以及新增,修改,刪除的鏈接入口。
  2. AddEditScore視圖,主要用於成績信息的新增和修改,共用一個視圖頁面。
  3. 成績課程不需要頁面,所以沒有對應視圖。

4.1. Score視圖

Score視圖,主要是成績的查詢和新增,修改,刪除的鏈接入口。涉及知識點如下:

  1. Score視圖頁面佈局採用Grid方式和StackPanel混合佈局,即整體佈局採用Grid,細微佈局採用StackPanel。
  2. 成績採用分頁列表的方式展示,需要用到DataGrid,及分頁控制項【WPF預設不提供分頁控制項,可自行編寫分頁控制項】。
  3. 查詢條件採用按鈕Button和文本框TextBox等組成,關於基礎控制項的使用,不再詳細論述,可參考其他文章。
  4. 在本系統的所有WPF視圖中,均需要引入Prism和 MAH組件。
  5. Score視圖中,所有的數據均採用Binding的方式與ViewModel進行交互。

Score視圖具體代碼,如下所示:

  1 <UserControl x:Class="SIMS.ScoreModule.Views.Score"
  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:i="http://schemas.microsoft.com/xaml/behaviors"
  7              xmlns:prism="http://prismlibrary.com/"
  8              xmlns:local="clr-namespace:SIMS.ScoreModule.Views"
  9              mc:Ignorable="d" 
 10              xmlns:mahApps="http://metro.mahapps.com/winfx/xaml/controls"
 11              xmlns:ctrls ="clr-namespace:SIMS.Utils.Controls;assembly=SIMS.Utils"
 12              prism:ViewModelLocator.AutoWireViewModel="True"
 13              d:DesignHeight="450" d:DesignWidth="800">
 14 
 15     <UserControl.Resources>
 16         <ResourceDictionary>
 17             <ResourceDictionary.MergedDictionaries>
 18                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
 19                 <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
 20                 <ResourceDictionary>
 21                     <Style x:Key="LinkButton" TargetType="Button">
 22                         <Setter Property="Background" Value="White"></Setter>
 23                         <Setter Property="Cursor" Value="Hand"></Setter>
 24                         <Setter Property="Margin" Value="3"></Setter>
 25                         <Setter Property="MinWidth" Value="80"></Setter>
 26                         <Setter Property="MinHeight" Value="25"></Setter>
 27                         <Setter Property="BorderThickness" Value="0 0 0 0"></Setter>
 28                     </Style>
 29                 </ResourceDictionary>
 30             </ResourceDictionary.MergedDictionaries>
 31         </ResourceDictionary>
 32     </UserControl.Resources>
 33     <i:Interaction.Triggers>
 34         <i:EventTrigger EventName="Loaded">
 35             <i:InvokeCommandAction Command="{Binding LoadedCommand}"></i:InvokeCommandAction>
 36         </i:EventTrigger>
 37     </i:Interaction.Triggers>
 38     <Grid>
 39         <Grid.RowDefinitions>
 40             <RowDefinition Height="Auto"></RowDefinition>
 41             <RowDefinition Height="Auto"></RowDefinition>
 42             <RowDefinition Height="*"></RowDefinition>
 43             <RowDefinition Height="Auto"></RowDefinition>
 44         </Grid.RowDefinitions>
 45         <TextBlock Text="成績信息" FontSize="20" Background="AliceBlue" Margin="2"></TextBlock>
 46         <StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center">
	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一個工作了6年的粉絲和我說, 最近面試感覺越來越難的,基本上都會問技術底層原理,甚至有些還會問到操作系統層面的知識。 我說,現在各個一線大廠有很多優秀的程式員畢業了,再加上市場大環境不好對程式員的需求量也在減少。 如果技術底子不好,確實找工作會很困難。 今天分享的問題是:”new String(“a ...
  • #所有流程 !!!不要修改為搶票,遵守法律法規是每一個中國公民應盡的責任,盜用並造成不良後果自負!!! ''' #可以實現買學生票,兒童票,殘疾票,成人票和所有能選的座位類別。 2022-05-22目前為止還是完全正常運行的,之後網頁改動就不一定了哦!!!!!!12306官網模擬買票:1.輸入賬號密 ...
  • 2 Sentinel 限流熔斷降級 Sentinel 可以簡單的分為 Sentinel 核心庫和 Dashboard。核心庫不依賴 Dashboard,但是結合 Dashboard 可以取得最好的效果。我們先來學習Sentinel 核心庫的使用,後面再學習Dashboard使用。 在我們項目中,用戶 ...
  • 題目描述 密碼要求: 1.長度超過8位 2.包括大小寫字母.數字.其它符號,以上四種至少三種 3.不能有長度大於2的包含公共元素的子串重覆 (註:其他符號不含空格或換行) 數據範圍:輸入的字元串長度滿足 1≤n≤100 輸入描述 一組字元串 輸入描述 如果符合要求輸出:OK,否則輸出NG 代碼和解題 ...
  • 前言 以下僅做相關知識的簡述,更深入的瞭解和學習,請自行查閱資料或留言。 一、Python簡介 Python請查看官網自行瞭解。 Python是一種編程語言,可以讓您更快地工作,並更有效地集成您的系統。 Python is a programming language that lets you w ...
  • Java 8是Java的一個重大版本,是目前企業中使用最廣泛的一個版本。 它支持函數式編程,新的Stream API 、新的日期 API等一系列新特性。 掌握Java8的新特性已經是java程式員的標配,掌握了它,就可以看懂公司里的代碼、高效率地處理大量集合數據以及消滅“嵌套地獄”等等。 ...
  • 0. 文章目的: 介紹變體的概念,並介紹其對C#的意義 1. 閱讀基礎 瞭解C#進階語言功能的使用(尤其是泛型、委托、介面) 2. 從示例入手,理解變體 變體這一概念用於描述存在繼承關係的類型間的轉化,這一概念並非只適用於C#,在許多其他的OOP語言中也都有變體概念。變體一共有三種:協變、逆變與不變 ...
  • 0. 文章目的 本文面向有一定.NET C#基礎知識的學習者,介紹C#中結構體定義、使用以及特點。 1. 閱讀基礎 瞭解C#基本語法 瞭解.NET中的棧與托管堆 2. 值類型 2.1 .NET的兩大類型 在.NET中,所有類型都是object類型的子類,而在object繁多的子類中,又可以將它們歸結 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...