总算忙过一段时间了,两个月前看了一点点关于 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() 方法中的窗体就意味着当前窗体作为主线程运行,此时关闭该窗体即整个程序都退出。
同时也要注意到窗体调用 showshowDialog 的区别(《
c# cs项目里面窗体的ShowDialog()和show()的区别》),简单来说,ShowDialog() 弹出的窗体为模式化窗体(此时,之前的窗体为父窗体,当前的窗体为子窗体),show() 弹出的窗体为 非模式化窗体,二者的区别:

  • 模式化窗体会使程序中断,直到关闭窗体
  • 打开窗体后不能替换到其他窗体
  • 子窗体和父窗体互斥,即子窗体打开后无法聚焦到父窗体上
  • 返回值不同分别为 dialogresultvoid

所以可以在 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 里的控件可以通过 PanelControls 属性进行访问,该属性返回一组 Control 列表,所以还需要强制转换为特定的 Form 类型。
主窗体内嵌子窗体的方式就是使用 Panel 控件,将子窗体设置到在 PanelControls 中,并显示,具体操作如下:

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#笔记(学生管理系统实战 - 用户登录)相关推荐

  1. 【学生管理系统】用户登录三种验证方式—图片验证、短信验证、邮件验证

    目录 一.页面需求展示 二.验证方式-按钮组件 三.手机短信验证 四.邮件验证 五.图片验证邮件验证

  2. Vue + Spring Boot 学习笔记01:实现用户登录功能

    Vue + Spring Boot 学习笔记01:实现用户登录功能 一.创建后端Spring Boot项目Book Management 二.创建前端Vue项目bm-vue 三.修改后端项目Book ...

  3. 【学生管理系统】用户管理之用户登录

    目录 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 ...

  4. Vue项目实战之电商后台管理系统(一) 用户登录模块

    目录 一.项目概述 二.项目初始化 2.1 前端项目初始化步骤 2.2 后台项目的环境安装配置 三.用户登录/登出功能实现 3.1 登录功能概述 3.1.1 登录状态保持 3.1.2 登录逻辑: 3. ...

  5. 学生管理系统:含注册登录操作

    目录 一.分包概况: 二.USER包 1.AMain类:主函数所在 2.User类:构造账号属性 3.PasswordOperate包:用于登录,注册,修改密码,查看账号操作 (1)Login类:登录 ...

  6. C++单链表学生管理系统(有登录界面)

    C++单链表 学生管理系统 这个程序是我好几天的心血,欢迎大家指正!!! 该程序需要新建三个txt文件.1.login.txt用来存放注册用户的用户名与密码. 2.login2.txt用于登录时将lo ...

  7. 实战 用户登录、session校验、分布式存储session

    实现登录功能 然后再创建login.css存放于在static下,css目录中,id 为 content 的 样式: #content {margin-left: 220px;margin-right ...

  8. 学生管理系统的注册登录以及管理的具体实现

    题目要求: 编写程序:实现登录注册功能,程序一进来如果没有账号就选择注册,如果有账号就直接登录. 注册功能的时候要输入注册账号.设置密码.输入确认密码.输入邮箱号码.输入性别.输入个人简介.输入你的身 ...

  9. 理想国Java学生管理系统实战教程+源码

    01.需求 使用所学知识制作一个学生管理系统,包含如下功能 查看所有学生 添加一个学生 删除一个学生 根据名字修改学生 根据名字查询学生 退出系统 说明 学生信息:姓名,性别,年龄 从控制台录入学生 ...

最新文章

  1. C#分析数据库结构,使用XSL模板自动生成代码
  2. 《Cortex-M0权威指南》之体系结构---异常和中断
  3. Duplicate property mapping of xxx found in xx 嵌套异常,重复的属性在映射中发现。
  4. 不写画面的网页程序设计,Web API、Web Service、WCF Service
  5. ubuntu 20 安装vnc_Windows 远程控制 Ubuntu 系统
  6. PythonOpenCV--Rtrees随机森林
  7. 核心指导网络由任务编码器_指导新编码员的最佳做法
  8. mybatis分页助手PageInfo参数含义
  9. jquery 获取元素图片_【jQuery】获取图片真实宽高
  10. vue for 初始值_vue全套教程(实操)就在这里
  11. Unix编程艺术-翻译-开篇
  12. CNC加工老师傅的经验分享 这些你都知道吗?
  13. 2022高教社杯 国赛数学建模 A题思路
  14. Machine Learning | (1) Scikit-learn与特征工程
  15. 基于文心大模型的剧本杀海报生成器(武侠篇)
  16. 一手掌控美食新鲜“灵魂”且融汇到生活的方方面面
  17. C++ QT调用python脚本并将软件打包发布
  18. 软件测试思想者 - “中华公网共图强”观后感
  19. 《啊哈算法》第四章 万能的搜索
  20. [题解]P5550 |Chino的数列

热门文章

  1. php分页教程,php实现分页的原理及步骤
  2. 怎么把pdf文件转换成jpg格式
  3. Sybase整合SpringBoot
  4. 浅谈企业引入设备巡检管理系统的必要性
  5. Dell R720 安装 win2003 64位 的安装步骤以及注意事项
  6. debian系统安装Thinkpad T410s的无线网卡驱动:centrino Advanced-N 6200 2x2 AGN
  7. deqin - 现实的身价表调查
  8. 在家远程使用公司用友ERP财务软件 【远程办公】
  9. js实现bind函数
  10. ----web前端 实验二