1.6. Windows Forms
WinForms 是 .NET 最经典的桌面 UI 框架,快速开发 Windows 桌面应用。
1.6.1. WinForms 概述
特性 |
说明 |
|---|---|
架构 |
基于 GDI+ 绘图,封装 Windows 控件 |
设计器 |
拖拽控件,所见即所得 |
事件模型 |
基于委托的事件驱动 |
适用场景 |
快速工具、内部管理系统、工业控制 |
.NET 支持 |
.NET Framework 全系列 + .NET 6+ |
1.6.2. 创建 WinForms 项目
dotnet new winforms -n MyWinFormsApp
cd MyWinFormsApp
dotnet run
1.6.2.1. 基本结构
// Form1.cs
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); // 设计器生成的代码
}
}
// Form1.Designer.cs(设计器自动维护)
partial class Form1
{
private System.ComponentModel.IContainer components = null;
private Button buttonOK;
private TextBox textBoxName;
private Label labelTitle;
private void InitializeComponent()
{
this.buttonOK = new Button();
this.textBoxName = new TextBox();
this.labelTitle = new Label();
// ... 属性设置
}
}
1.6.3. 常用控件
// 标签
var label = new Label
{
Text = "用户名:",
Location = new Point(20, 20),
Size = new Size(80, 25),
Font = new Font("微软雅黑", 10)
};
// 文本框
var textBox = new TextBox
{
Location = new Point(100, 20),
Size = new Size(200, 25),
PasswordChar = '*' // 密码模式
};
// 按钮
var button = new Button
{
Text = "登录",
Location = new Point(100, 60),
Size = new Size(100, 35),
BackColor = Color.LightBlue,
FlatStyle = FlatStyle.Flat
};
button.Click += ButtonLogin_Click; // 事件绑定
// 下拉框
var comboBox = new ComboBox
{
Location = new Point(100, 60),
DropDownStyle = ComboBoxStyle.DropDownList
};
comboBox.Items.AddRange(["选项1", "选项2", "选项3"]);
// 数据表格
var dataGrid = new DataGridView
{
Location = new Point(20, 100),
Size = new Size(400, 200),
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
AllowUserToAddRows = false,
ReadOnly = true
};
dataGrid.DataSource = userList;
1.6.4. 事件处理
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
Load += MainForm_Load; // 窗体加载
FormClosing += MainForm_FormClosing; // 关闭前
}
private void MainForm_Load(object? sender, EventArgs e)
{
// 初始化数据
LoadUserData();
}
private void MainForm_FormClosing(object? sender,
FormClosingEventArgs e)
{
if (HasUnsavedChanges)
{
var result = MessageBox.Show(
"有未保存的修改,确定退出?",
"确认",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
e.Cancel = (result == DialogResult.No);
}
}
private void ButtonLogin_Click(object? sender, EventArgs e)
{
string user = textBoxUser.Text;
string pass = textBoxPassword.Text;
if (Authenticate(user, pass))
{
MessageBox.Show("登录成功!", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
MessageBox.Show("用户名或密码错误!", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
1.6.5. 对话框
// 消息框
MessageBox.Show("消息内容", "标题");
MessageBox.Show("确认删除?", "确认",
MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Warning);
// 打开文件
using var openDlg = new OpenFileDialog
{
Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*",
Multiselect = false,
InitialDirectory = Environment.GetFolderPath(
Environment.SpecialFolder.Desktop)
};
if (openDlg.ShowDialog() == DialogResult.OK)
{
string path = openDlg.FileName;
// 处理文件...
}
// 保存文件
using var saveDlg = new SaveFileDialog
{
Filter = "图片文件|*.png;*.jpg",
DefaultExt = "png"
};
if (saveDlg.ShowDialog() == DialogResult.OK)
{
image.Save(saveDlg.FileName);
}
// 文件夹选择
using var folderDlg = new FolderBrowserDialog();
if (folderDlg.ShowDialog() == DialogResult.OK)
{
string path = folderDlg.SelectedPath;
}
1.6.6. MDI 多文档界面
// 主窗体设置为 MDI 容器
public partial class MainForm : Form
{
public MainForm()
{
IsMdiContainer = true; // 设置为 MDI 容器
var menu = new MenuStrip();
var fileMenu = menu.Items.Add("文件") as ToolStripMenuItem;
fileMenu.DropDownItems.Add("打开", null, OpenChildForm);
MainMenuStrip = menu;
Controls.Add(menu);
}
private void OpenChildForm(object? sender, EventArgs e)
{
var child = new ChildForm();
child.MdiParent = this; // 设置在容器内显示
child.Show();
}
}
1.6.7. 自定义控件
// 继承现有控件
public class NumericTextBox : TextBox
{
public NumericTextBox()
{
this.Font = new Font("Consolas", 12);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
// 只允许数字输入
if (!char.IsDigit(e.KeyChar) &&
!char.IsControl(e.KeyChar))
e.Handled = true;
base.OnKeyPress(e);
}
}
// UserControl(组合多个控件)
public partial class AddressControl : UserControl
{
public AddressControl()
{
InitializeComponent(); // 设计器支持
}
public string Street => textStreet.Text;
public string City => textCity.Text;
public string ZipCode => textZip.Text;
}
小技巧
WinForms 开发建议:
使用
using管理 GDI 资源(Brush、Pen、Font)耗时操作使用
async/await避免 UI 阻塞跨线程访问 UI 用
Invoke/BeginInvoke考虑 MVP (Model-View-Presenter) 模式分离逻辑