C#笔记(学生管理系统实战 - 用户登录)
总算忙过一段时间了,两个月前看了一点点关于 C# 的实战视频,现在看回来居然忘得七七八八,果然学习还是要写笔记,好记性不如烂笔头。。
1 项目框架
- 用户界面模块
- 数据访问模块 DAL(即如同 Service 层、Dao 层 与 Mapper 层,其中还包含如
SQLHelper
类) - 数据库映射实体类模块 Models(即 Bean 层)
- 其它辅助类(如数字验证)
- 程序的配置文件
本项目基于两层架构进行设计,用户界面模块为 表现层,数据访问模块为 数据访问层,而实体类模块并不能算一个独立的数据层,它只能算是程序中的一个模块。
注意:
1、在解决方案
下右键选择新增类库
,类库之间的引用,右键打开对应的模块引用
点击添加引用
,选择对应的类库名即可。
2、在模块中添加的类
默认的访问修饰符是internal
,所以要在外部模块中引用就需要显式地声明该类访问修饰符为public
。
3、在添加完类库
之后,要右键解决方案
点击生成解决方案
或者 右键对应的模块点击重新生成
,这样对应的类库才能编译到对应的dll
文件中。
1.1 数据访问模块
由于数据访问模块需要与数据库进行链接访问,所以其下新增的类需要添加以下命名空间:
// 数据库使用 sqlServer
using System.Data;
using System.Data.SqlClient;
// 数据库使用 mysql
using System.Data;
using MySql.Data.MySqlClient;
1.1.1 SQLHelper
类
在 数据访问模块(DAL) 中,基本都是 Service
类,而像 SQLHelper
这种工具类为了区分开来,最好就是在 数据访问模块(DAL)下新增一个文件夹,并将其声明在此。
注意:如果直接新增如名为
SQLHelper
的文件夹,并在其直接添加SQLHelper
类,此时SQLHelper
的命名空间即为DAL.SQLHelper
,这样即使是在 DAL 模块下的其他Service
类也需要显式引用该命名空间才能使用SQLHelper
类,所以最简洁的方法是先直接在 DAL 模块下声明SQLHelper
类,声明完之后直接拖动到SQLHelper
文件夹中,此时该命名空间也依旧是DAL
。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using MySql.Data.MySqlClient;
using System.Configuration;// 引入读取配置文件类所在的命名空间,要在根目录下建立配置文件,比如此项目的根目录是在 StudentManager 表现层当中namespace DAL
{public class SQLHelper{public static string connString = ConfigurationManager.ConnectionStrings["connString"].ToString();/// <summary>/// 增,删,改/// </summary>/// <param name="sql"></param>public static int executeNonQuery(string sql){MySqlConnection conn = new MySqlConnection(connString);MySqlCommand cmd = new MySqlCommand(sql, conn);try{conn.Open();int result = cmd.ExecuteNonQuery();return result;}catch (Exception ex){// 写入日志throw ex;}finally{conn.Close();}}/// <summary>/// 获取单一数据/// </summary>/// <param name="sql"></param>/// <returns></returns>public static object GetSingleResult(string sql){MySqlConnection conn = new MySqlConnection(connString);MySqlCommand cmd = new MySqlCommand(sql, conn);try{conn.Open();object result = cmd.ExecuteScalar();return result;}catch (Exception ex){// 写入日志throw ex;}finally{conn.Close();}}/// <summary>/// 获取 结果集 的查询/// </summary>/// <param name="sql"></param>/// <returns></returns>public static MySqlDataReader getReader(string sql){MySqlConnection conn = new MySqlConnection(connString);MySqlCommand cmd = new MySqlCommand(sql, conn);try{conn.Open();MySqlDataReader result = cmd.ExecuteReader(CommandBehavior.CloseConnection); // 关闭数据库链接,不能在 finally 语句中关闭链接,因为如果关闭了,MySqlDataReader 而又尚未读取,关闭之后 MySqlDataReader 也就读取不到了return result;}catch (Exception ex){// todo 写入日志throw ex;conn.Close();}}}
}
值得注意的是,链接数据库的字符串需要声明在配置文件中,这样修改链接字符串就无需重新编译程序,因此就要学习 C# 如何使用配置文件了。
1.1.2 配置文件 App.config
参考文章:《C# 配置文件App.config的使用操作》
在 表现层模块中即 winform 模块右键新建配置文件 App.config
(因为表现层所在的目录是将来应用程序启动时的根目录),然后添加相关的子节点,如添加数据库链接相关信息,节点名称可以为 connectionStrings
,eg:
<configuration><!-- 数据库链接信息 --><connectionStrings><add name="connString" connectionString="Server=127.0.0.1;port=3306;user=root;password=123456;database=studentmanager;"/></connectionStrings>
</configuration>
此时在 DAL 模块中要使用该配置文件,就需要先在模块引用中添加 System.Configuration
引用,然后在类中显式的引用命名空间:
using System.Configuration;
最后就可以使用形如 ConfigurationManager.ConnectionStrings["connString"].ToString()
进行对应数据的获取了。
2 用户登录
在项目的整体框架都搭建好之后,就需要理一下程序的流程了,其实也很简单,就是主线程显示登录窗体,输入账号密码,如果正确主程序就打开主界面,错误就返回信息,不登录点击退出就直接退出主线程,如果登录正确的同时还需要保存用户信息。
Program.cs
是程序启动的入口点,即登录窗口体也需要在此处调用显示。此时要注意的是,登录窗体不能作为参数地调用 Application.Run()
。因为放置在 Application.run()
方法中的窗体就意味着当前窗体作为主线程运行,此时关闭该窗体即整个程序都退出。
同时也要注意到窗体调用 show
与 showDialog
的区别(《
c# cs项目里面窗体的ShowDialog()和show()的区别》),简单来说,ShowDialog()
弹出的窗体为模式化窗体(此时,之前的窗体为父窗体,当前的窗体为子窗体),show()
弹出的窗体为 非模式化窗体,二者的区别:
- 模式化窗体会使程序中断,直到关闭窗体
- 打开窗体后不能替换到其他窗体
- 子窗体和父窗体互斥,即子窗体打开后无法聚焦到父窗体上
- 返回值不同分别为
dialogresult
和void
所以可以在 Progarm.cs
可以添加:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using Models;namespace StudentManager
{static class Program{// 相当于全局变量public static Admin currentAdmin = null; // 当前用户/// <summary>/// 应用程序的主入口点。/// </summary>[STAThread]static void Main(){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);// 显示登录窗口FrmUserLogin frmUserLogin = new FrmUserLogin();DialogResult result = frmUserLogin.ShowDialog();// 获取 登录窗口 返回的信息if (result == DialogResult.OK){Application.Run(new FrmMain()); // 主线程窗口}else{Application.Exit(); // 退出整个程序}}}
}
待登录窗口中的数据验证之后,即可获取数据库中的数据进行校对,这个逻辑就卸载 DAL 模块之中,然后比校成功之后,就需要修改窗体的返回值 DialogResult
,此时可以如以下语句进行修改:
this.DialogResult = DialogResult.OK;
在程序中一旦设置
DialogResult
的值,接下来就会自动执行close()
的方法,所以其实没有必要写this.close()
关闭当前窗体。
同时,还需要保存用户信息,这里保存用户信息的方式是将用户信息设置为 全局静态变量,而程序的全局静态变量声明在 Program.cs
文件中,在其它的窗体文件可以使用 Program.currentUserMsg
的形式进行访问与修改。
3 关于主窗体内嵌子窗体
首先要理解 Panel
控件,Windows 窗体 Panel
控件用于为其他控件提供可识别的分组(嵌板,就是一个面板容器)。而分组在 Panel
里的控件可以通过 Panel
的 Controls
属性进行访问,该属性返回一组 Control
列表,所以还需要强制转换为特定的 Form
类型。
主窗体内嵌子窗体的方式就是使用 Panel
控件,将子窗体设置到在 Panel
的 Controls
中,并显示,具体操作如下:
private void openForm(Form formObj){formObj.TopLevel = false; // 将子窗体设置为非顶级控件,作为子窗体内嵌必须formObj.WindowState = FormWindowState.Maximized; // 设置子窗口最大化formObj.FormBorderStyle = FormBorderStyle.None; // 消除子窗口边框this.panel1.Controls.Add(formObj); // 添加到 panel1 中,此时 formObj 的父窗体 parent 已经设置为 panel1formObj.Show(); // 显示子窗体}
关闭内嵌子窗体,如下
private void closeFrom()
{// 循环面板 Contorls 列表,将窗体关闭并移出foreach (Control itemOfControl in this.panel1.Controls) {if (itemOfControl is Form){Form formObj = (Form)itemOfControl;formObj.Close();this.panel1.Controls.Remove(itemOfControl);}}
}
5 优化用户体验
5.1 窗体的 FormClosing
事件
《C# 关于MessageBox.Show()函数》
为了防止用户的误操作,很多时候在关闭窗口时,系统会弹出询问窗口,这就需要使用到 FormClosing
事件,窗体在调用 Close
方法的时候,都会先执行 FormClosing
事件,所以弹出询问窗口的逻辑就可以写在这个事件中(查看窗体的属性,可以在事件列表中找到该事件进行添加),FormClosing
事件有个 FormClosingEventArgs
参数,将该参数的 Cancel
属性设置为 true
即可取消窗体的关闭了。
与此同时还会使用到 MessageBox.Show()
,它被设计为弹出提示框,返回一个 DialogResult
结果,接受四个参数依次为:
- 内容
- 标题
- 按键
- 图标
- 默认激活按键
private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
{DialogResult dialogResult = MessageBox.Show("是否退出程序", "询问", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);if (dialogResult == DialogResult.Cancel){e.Cancel = true;}
}
5.2 使用代码设置背景图片
想要程序好看一点可能需要在某些地方使用以下背景图片,可以直接的在对应的空间属性页面中设置 BackgroundImage
属性直接导入图片,也可以在控件的初始化函数中使用代码进行设置,设置控件背景图片属性的类型为 Image
类,可以使用 Image
类的 FromFile
方法从传入对应文件路径,获取对应图片的 Image
对象实例,Image
类的命名空间在 System.Drawing
,值得注意的是,使用相对路径时,是基于主程序所在文件,如 F:\c sharp\StudentManager\StudentManager\bin\Debug
,eg:
this.panel1.BackgroundImage = Image.FromFile("./static/img/mainBackgroundImg.jpg");
5.3 登录窗口检测 Enter
按键事件
想要优化的功能就类似使用 Tab
按键后,输入框的焦点会下移,此时就需要监听输入控件的按键事件,可以在对应的控件的事件列表中进行添加,按键事件为 KeyDown
,其中参数 KeyEventArgs
有一个 KeyValue
属性用来存储用户输入的按键代码,而 Enter
按键的为 13
,例如:
private void userName_KeyDown(object sender, KeyEventArgs e)
{if (this.userName.Text.Length == 0){return;}// 13 为 Enter 按键的代码,如果检测到按键为 Enter,则聚焦密码输入框if (e.KeyValue == 13){this.pw.Focus();}
}
C#笔记(学生管理系统实战 - 用户登录)相关推荐
- 【学生管理系统】用户登录三种验证方式—图片验证、短信验证、邮件验证
目录 一.页面需求展示 二.验证方式-按钮组件 三.手机短信验证 四.邮件验证 五.图片验证邮件验证
- Vue + Spring Boot 学习笔记01:实现用户登录功能
Vue + Spring Boot 学习笔记01:实现用户登录功能 一.创建后端Spring Boot项目Book Management 二.创建前端Vue项目bm-vue 三.修改后端项目Book ...
- 【学生管理系统】用户管理之用户登录
目录 2. 用户管理 2.1 环境搭建 2.1.1 前端环境 2.1.2 后端环境(9000) 2.2 用户登录 2.2.1 需求 2.2.2 后端实现 2.2.3 前端实现 2.3 首页 2.3.1 ...
- Vue项目实战之电商后台管理系统(一) 用户登录模块
目录 一.项目概述 二.项目初始化 2.1 前端项目初始化步骤 2.2 后台项目的环境安装配置 三.用户登录/登出功能实现 3.1 登录功能概述 3.1.1 登录状态保持 3.1.2 登录逻辑: 3. ...
- 学生管理系统:含注册登录操作
目录 一.分包概况: 二.USER包 1.AMain类:主函数所在 2.User类:构造账号属性 3.PasswordOperate包:用于登录,注册,修改密码,查看账号操作 (1)Login类:登录 ...
- C++单链表学生管理系统(有登录界面)
C++单链表 学生管理系统 这个程序是我好几天的心血,欢迎大家指正!!! 该程序需要新建三个txt文件.1.login.txt用来存放注册用户的用户名与密码. 2.login2.txt用于登录时将lo ...
- 实战 用户登录、session校验、分布式存储session
实现登录功能 然后再创建login.css存放于在static下,css目录中,id 为 content 的 样式: #content {margin-left: 220px;margin-right ...
- 学生管理系统的注册登录以及管理的具体实现
题目要求: 编写程序:实现登录注册功能,程序一进来如果没有账号就选择注册,如果有账号就直接登录. 注册功能的时候要输入注册账号.设置密码.输入确认密码.输入邮箱号码.输入性别.输入个人简介.输入你的身 ...
- 理想国Java学生管理系统实战教程+源码
01.需求 使用所学知识制作一个学生管理系统,包含如下功能 查看所有学生 添加一个学生 删除一个学生 根据名字修改学生 根据名字查询学生 退出系统 说明 学生信息:姓名,性别,年龄 从控制台录入学生 ...
最新文章
- C#分析数据库结构,使用XSL模板自动生成代码
- 《Cortex-M0权威指南》之体系结构---异常和中断
- Duplicate property mapping of xxx found in xx 嵌套异常,重复的属性在映射中发现。
- 不写画面的网页程序设计,Web API、Web Service、WCF Service
- ubuntu 20 安装vnc_Windows 远程控制 Ubuntu 系统
- PythonOpenCV--Rtrees随机森林
- 核心指导网络由任务编码器_指导新编码员的最佳做法
- mybatis分页助手PageInfo参数含义
- jquery 获取元素图片_【jQuery】获取图片真实宽高
- vue for 初始值_vue全套教程(实操)就在这里
- Unix编程艺术-翻译-开篇
- CNC加工老师傅的经验分享 这些你都知道吗?
- 2022高教社杯 国赛数学建模 A题思路
- Machine Learning | (1) Scikit-learn与特征工程
- 基于文心大模型的剧本杀海报生成器(武侠篇)
- 一手掌控美食新鲜“灵魂”且融汇到生活的方方面面
- C++ QT调用python脚本并将软件打包发布
- 软件测试思想者 - “中华公网共图强”观后感
- 《啊哈算法》第四章 万能的搜索
- [题解]P5550 |Chino的数列