C# WinForms 桌面应用
最后更新: 2025年11月26日
技术栈概述
C# WinForms 是微软.NET平台的桌面应用开发技术,使用C#语言和Windows Forms框架构建原生Windows应用程序,具有开发效率高、界面美观的特点。
技术组成
| 组件 | 说明 |
|---|---|
| C# | 编程语言 |
| .NET Framework | 4.7.2+ 或 .NET 6+ |
| Windows Forms | GUI框架 |
| ADO.NET | 数据库访问 |
| Visual Studio | 开发IDE |
核心特性
- ✅ 原生Windows:最佳的Windows体验
- ✅ 可视化设计:拖拽式界面设计
- ✅ 丰富控件:DataGridView、TreeView等
- ✅ 开发效率高:快速构建企业应用
C# WinForms 框架变体说明
系统提供两个 C# WinForms 变体,满足不同需求:
C_SHARP (基础版) - 适合简单工具
| 特性 | 说明 |
|---|---|
| 平台代码 | C_SHARP |
| 技术栈 | .NET Framework + WinForms |
| 生成内容 | 基础 Forms、数据访问层、实体类 |
| 适用场景 | 简单工具、小型应用、快速开发 |
| 模板目录 | project-csharp |
C_SHARP2 (增强版) - 完整 CRUD 系统
| 特性 | 说明 |
|---|---|
| 平台代码 | C_SHARP2 |
| 技术栈 | .NET Framework + WinForms |
| 生成内容 | 为每个实体生成 4 种 Forms |
| 适用场景 | 完整 CRUD 管理系统、企业应用 |
| 模板目录 | project-csharp2 |
C_SHARP2 为每个实体额外生成的 Forms:
| Form | 文件名 | 说明 |
|---|---|---|
| 数据列表 Form | FormData.cs | 显示所有数据(DataGridView) |
| 新增数据 Form | FormAdd.cs | 新增数据表单 |
| 编辑数据 Form | FormEdit.cs | 编辑数据表单 |
| 查看详情 Form | FormDetail.cs | 查看数据详情(只读) |
变体选择建议:
| 您的需求 | 推荐变体 |
|---|---|
| 简单工具、小型应用 | C_SHARP (基础版) |
| 完整 CRUD 管理系统 | C_SHARP2 (增强版) |
💡 提示:两个变体的后端代码(DAL、BLL、Models)完全相同,区别仅在 UI Forms 数量。C_SHARP2 为每个实体自动生成完整的增删改查界面。
适用场景
| 场景 | 说明 |
|---|---|
| Windows桌面软件 | 企业内部管理系统 |
| 数据管理工具 | 数据库客户端、报表工具 |
| 课程设计 | C#或.NET课程作业 |
| 小型ERP | 进销存、财务管理 |
项目结构
ProjectName/ ├── ProjectName.sln # 解决方案文件 ├── ProjectName/ │ ├── Program.cs # 程序入口 │ ├── App.config # 配置文件 │ ├── Models/ # 实体类 │ │ └── Student.cs │ ├── DAL/ # 数据访问层 │ │ ├── DBHelper.cs │ │ └── StudentDAL.cs │ ├── BLL/ # 业务逻辑层 │ │ └── StudentBLL.cs │ └── Forms/ # 窗体 │ ├── MainForm.cs │ ├── MainForm.Designer.cs │ ├── StudentListForm.cs │ └── StudentEditForm.cs └── sql/ └── schema.sql
核心代码示例
程序入口 (Program.cs)
using System; using System.Windows.Forms; namespace ProjectName { static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } }
实体类 (Student.cs)
using System; namespace ProjectName.Models { public class Student { public long Id { get; set; } public string Name { get; set; } public string StudentNo { get; set; } public int Gender { get; set; } public long? ClassId { get; set; } public DateTime CreateTime { get; set; } public DateTime UpdateTime { get; set; } // 显示用属性 public string GenderText => Gender == 1 ? "男" : "女"; } }
数据库帮助类 (DBHelper.cs)
using System; using System.Configuration; using System.Data; using System.Data.SqlClient; namespace ProjectName.DAL { public static class DBHelper { private static readonly string ConnStr = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString; public static SqlConnection GetConnection() { return new SqlConnection(ConnStr); } public static DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = GetConnection()) { using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) cmd.Parameters.AddRange(parameters); SqlDataAdapter adapter = new SqlDataAdapter(cmd); DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = GetConnection()) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) cmd.Parameters.AddRange(parameters); return cmd.ExecuteNonQuery(); } } } public static object ExecuteScalar(string sql, params SqlParameter[] parameters) { using (SqlConnection conn = GetConnection()) { conn.Open(); using (SqlCommand cmd = new SqlCommand(sql, conn)) { if (parameters != null) cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } } } } }
数据访问层 (StudentDAL.cs)
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using ProjectName.Models; namespace ProjectName.DAL { public class StudentDAL { public List<Student> GetAll() { string sql = "SELECT * FROM student ORDER BY id DESC"; DataTable dt = DBHelper.ExecuteDataTable(sql); List<Student> list = new List<Student>(); foreach (DataRow row in dt.Rows) { list.Add(MapToEntity(row)); } return list; } public Student GetById(long id) { string sql = "SELECT * FROM student WHERE id = @id"; DataTable dt = DBHelper.ExecuteDataTable(sql, new SqlParameter("@id", id)); if (dt.Rows.Count > 0) return MapToEntity(dt.Rows[0]); return null; } public int Insert(Student entity) { string sql = @"INSERT INTO student(name, student_no, gender, class_id, create_time) VALUES(@name, @studentNo, @gender, @classId, @createTime)"; return DBHelper.ExecuteNonQuery(sql, new SqlParameter("@name", entity.Name), new SqlParameter("@studentNo", entity.StudentNo), new SqlParameter("@gender", entity.Gender), new SqlParameter("@classId", (object)entity.ClassId ?? DBNull.Value), new SqlParameter("@createTime", DateTime.Now)); } public int Update(Student entity) { string sql = @"UPDATE student SET name=@name, student_no=@studentNo, gender=@gender, class_id=@classId, update_time=@updateTime WHERE id=@id"; return DBHelper.ExecuteNonQuery(sql, new SqlParameter("@id", entity.Id), new SqlParameter("@name", entity.Name), new SqlParameter("@studentNo", entity.StudentNo), new SqlParameter("@gender", entity.Gender), new SqlParameter("@classId", (object)entity.ClassId ?? DBNull.Value), new SqlParameter("@updateTime", DateTime.Now)); } public int Delete(long id) { string sql = "DELETE FROM student WHERE id = @id"; return DBHelper.ExecuteNonQuery(sql, new SqlParameter("@id", id)); } private Student MapToEntity(DataRow row) { return new Student { Id = Convert.ToInt64(row["id"]), Name = row["name"].ToString(), StudentNo = row["student_no"].ToString(), Gender = Convert.ToInt32(row["gender"]), ClassId = row["class_id"] == DBNull.Value ? null : (long?)Convert.ToInt64(row["class_id"]), CreateTime = Convert.ToDateTime(row["create_time"]), UpdateTime = row["update_time"] == DBNull.Value ? DateTime.MinValue : Convert.ToDateTime(row["update_time"]) }; } } }
主窗体 (MainForm.cs)
using System; using System.Windows.Forms; namespace ProjectName.Forms { public partial class MainForm : Form { public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { // 初始化菜单 ToolStripMenuItem studentMenu = new ToolStripMenuItem("学生管理"); studentMenu.Click += (s, args) => ShowChildForm(new StudentListForm()); menuStrip1.Items.Add(studentMenu); } private void ShowChildForm(Form form) { form.MdiParent = this; form.WindowState = FormWindowState.Maximized; form.Show(); } } }
列表窗体 (StudentListForm.cs)
using System; using System.Windows.Forms; using ProjectName.BLL; using ProjectName.Models; namespace ProjectName.Forms { public partial class StudentListForm : Form { private StudentBLL studentBLL = new StudentBLL(); public StudentListForm() { InitializeComponent(); InitDataGridView(); LoadData(); } private void InitDataGridView() { dataGridView1.AutoGenerateColumns = false; dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect; dataGridView1.MultiSelect = false; dataGridView1.AllowUserToAddRows = false; dataGridView1.ReadOnly = true; dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "Id", HeaderText = "ID", Width = 60 }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "Name", HeaderText = "姓名", Width = 100 }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "StudentNo", HeaderText = "学号", Width = 120 }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "GenderText", HeaderText = "性别", Width = 60 }); dataGridView1.Columns.Add(new DataGridViewTextBoxColumn { DataPropertyName = "CreateTime", HeaderText = "创建时间", Width = 150 }); } private void LoadData() { dataGridView1.DataSource = studentBLL.GetAll(); } private void btnAdd_Click(object sender, EventArgs e) { StudentEditForm form = new StudentEditForm(null); if (form.ShowDialog() == DialogResult.OK) { LoadData(); } } private void btnEdit_Click(object sender, EventArgs e) { if (dataGridView1.CurrentRow == null) { MessageBox.Show("请先选择一行", "提示"); return; } Student student = dataGridView1.CurrentRow.DataBoundItem as Student; StudentEditForm form = new StudentEditForm(student); if (form.ShowDialog() == DialogResult.OK) { LoadData(); } } private void btnDelete_Click(object sender, EventArgs e) { if (dataGridView1.CurrentRow == null) { MessageBox.Show("请先选择一行", "提示"); return; } if (MessageBox.Show("确定要删除吗?", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes) { Student student = dataGridView1.CurrentRow.DataBoundItem as Student; studentBLL.Delete(student.Id); LoadData(); } } private void btnRefresh_Click(object sender, EventArgs e) { LoadData(); } } }
配置文件 (App.config)
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="DefaultConnection" connectionString="Server=localhost;Database=your_database;User Id=sa;Password=your_password;" providerName="System.Data.SqlClient" /> </connectionStrings> </configuration>
运行说明
开发环境
- 使用Visual Studio打开.sln文件
- 修改App.config中的数据库连接字符串
- 按F5运行
发布部署
- 右键项目 → 发布
- 选择文件夹发布
- 将发布文件夹复制到目标机器
- 确保目标机器安装了.NET Framework
数据库支持
支持的数据库类型
| 数据库 | 版本 | NuGet 包 | 连接字符串示例 |
|---|---|---|---|
| MySQL | 5.7+ | MySql.Data | Server=localhost;Database=your_db;Uid=root;Pwd=password; |
| SQLite | 3.x | System.Data.SQLite | Data Source=database.db;Version=3; |
| SQL Server | 2012+ | 内置 | Server=localhost;Database=your_db;User Id=sa;Password=pwd; |
⚠️ 注意:系统当前仅支持以上 3 种数据库。如需其他数据库(如 PostgreSQL、Oracle),需要手动修改配置和驱动。
配置方法(App.config):
<connectionStrings> <add name="DefaultConnection" connectionString="Server=localhost;Database=your_database;User Id=sa;Password=your_password;" providerName="System.Data.SqlClient" /> </connectionStrings>
常见问题
Q1: C_SHARP 和 C_SHARP2 应该选哪个?
推荐根据项目复杂度选择:
选择 C_SHARP (基础版):
- ✅ 简单工具、小型应用
- ✅ 快速开发原型
- ✅ 课程作业(不需要完整 CRUD 界面)
选择 C_SHARP2 (增强版):
- ✅ 完整的管理系统(需要增删改查界面)
- ✅ 企业内部应用
- ✅ 数据管理工具
区别总结:C_SHARP2 为每个实体自动生成 4 种 Forms(列表、新增、编辑、详情),节省大量开发时间。
Q2: 连接SQL Server失败?
检查:
- SQL Server服务是否启动
- 是否启用TCP/IP协议
- 防火墙是否放行1433端口
- App.config 中连接字符串是否正确
Q3: 使用MySQL数据库?
步骤:
- 安装 MySql.Data NuGet 包:
Install-Package MySql.Data - 修改 DBHelper.cs 中的连接字符串:
private static readonly string ConnStr = "Server=localhost;Database=your_db;Uid=root;Pwd=password;"; - 修改 SqlConnection 为 MySqlConnection
Q4: 使用 SQLite 数据库?
步骤:
- 安装 System.Data.SQLite NuGet 包
- 修改连接字符串:
private static readonly string ConnStr = "Data Source=database.db;Version=3;"; - 修改 SqlConnection 为 SQLiteConnection
Q5: DataGridView 中文乱码?
解决方案:
- 确保数据库编码为 UTF-8
- 在连接字符串中添加:
;CharSet=utf8;
Q6: 为什么选择 WinForms?
WinForms 的优势:
- ✅ 原生 Windows 体验,性能最佳
- ✅ 可视化设计器,拖拽式开发
- ✅ 丰富的控件库(DataGridView、TreeView 等)
- ✅ 开发效率高,适合企业内部应用
适合场景:企业内部管理系统、数据管理工具、课程设计
💡 提示:WinForms是Windows平台最成熟的桌面开发技术,适合快速开发企业内部应用。
本文对您有帮助吗?
提交反馈