使用 DataGridView 控件展示数据(内存),完成一个 Minimum CRUD Demo:
DataGridViewExtentions.cs#
using System.Reflection;
namespace ConsoleApp.WindowsFormTests
{
public static class ExtensionMethods
{
// 启用双缓冲机制,减少 UI 控件重绘时的闪烁现象
public static void DoubleBuffered(this DataGridView dgv, bool setting)
{
Type dgvType = dgv.GetType();
PropertyInfo? pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
pi!.SetValue(dgv, setting, null);
}
}
}
FrmMain.cs#
using System.Data;
namespace ConsoleApp.WindowsFormTests
{
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
}
private readonly DataTable _dataTable = new();
private void FrmMain_Load(object sender, EventArgs e)
{
InitialDataTable();
InitalDataGridView();
btnAdd.Click += BtnAdd_Click;
btnUpdate.Click += BtnUpdate_Click;
btnDelete.Click += BtnDelete_Click;
}
private void BtnDelete_Click(object? sender, EventArgs e)
{
if (!AnySelectedRow())
{
MessageBox.Show("请先选择要删除的行");
return;
}
var row = GetSelectedRow();
var id = row.Cells["Id"].Value;
var nickName = row.Cells["NickName"].Value;
var dialogResult = MessageBox.Show($"确定要删除 {nickName} 吗?", "删除确认", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.No) return;
DeleteDataRow(id);
ClearDataGridViewSelection();
}
private void BtnUpdate_Click(object? sender, EventArgs e)
{
if (!AnySelectedRow())
{
MessageBox.Show("请先选择要修改的行");
return;
}
var nickName = txtNickName.Text.Trim();
if (string.IsNullOrWhiteSpace(nickName))
{
txtNickName.Focus();
return;
}
var id = GetSelectedRow().Cells["Id"].Value;
UpdateDataRow(id!, nickName);
}
private void BtnAdd_Click(object? sender, EventArgs e)
{
var nickName = txtNickName.Text.Trim();
if (string.IsNullOrWhiteSpace(nickName))
{
txtNickName.Focus();
return;
}
dataGridView1.ClearSelection();
AddDataRow(nickName);
// 首次添加数据,dataGridView 会选中第一条数据,这里清除默认选中的行为
if (_dataTable.Rows.Count == 1)
{
ClearDataGridViewSelection();
}
txtNickName.Clear();
txtNickName.Focus();
}
private void DataGridView1_SelectionChanged(object? sender, EventArgs e)
{
if (!AnySelectedRow()) return;
var selectedRow = GetSelectedRow();
txtNickName.Text = selectedRow.Cells["NickName"].Value.ToString();
}
private void AddDataRow(string nickName)
{
_dataTable.Rows.Add(Guid.NewGuid(), nickName);
}
private void UpdateDataRow(object? key, string nickName)
{
var row = _dataTable.Rows.Find(key);
row!["NickName"] = nickName;
}
private void DeleteDataRow(object? key)
{
var row = _dataTable.Rows.Find(key);
row!.Delete();
}
private void InitialDataTable()
{
var idColumn = _dataTable.Columns.Add("Id");
_dataTable.Columns.Add("NickName");
_dataTable.PrimaryKey = new DataColumn[] { idColumn };
}
private void InitalDataGridView()
{
dataGridView1.DataSource = _dataTable;
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
dataGridView1.MultiSelect = false;
dataGridView1.DoubleBuffered(true);
dataGridView1.RowPrePaint += DataGridView1_RowPrePaint;
dataGridView1.SelectionChanged += DataGridView1_SelectionChanged;
}
private void ClearDataGridViewSelection()
{
dataGridView1.ClearSelection();
dataGridView1.CurrentCell = null;
}
private bool AnySelectedRow() => dataGridView1.CurrentRow != null;
private DataGridViewRow GetSelectedRow() => dataGridView1.CurrentRow;
// 阻止绘制焦点样式,改善视觉效果,使行在没有焦点时看起来更加一致或符合设计需求
private void DataGridView1_RowPrePaint(object? sender, DataGridViewRowPrePaintEventArgs e) => e.PaintParts &= ~DataGridViewPaintParts.Focus;
}
}
FrmMain.Designer.cs#
namespace ConsoleApp.WindowsFormTests
{
partial class FrmMain
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理正在使用的任何资源。
/// </summary>
/// <param name="disposing">true 如果应释放受管资源;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer 生成的代码
/// <summary>
/// 设计器支持所需的方法 - 请勿使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
txtNickName = new TextBox();
btnAdd = new Button();
dataGridView1 = new DataGridView();
btnUpdate = new Button();
btnDelete = new Button();
((System.ComponentModel.ISupportInitialize)dataGridView1).BeginInit();
SuspendLayout();
//
// txtNickName
//
txtNickName.Location = new Point(71, 47);
txtNickName.Name = "txtNickName";
txtNickName.Size = new Size(125, 27);
txtNickName.TabIndex = 0;
//
// btnAdd
//
btnAdd.Location = new Point(235, 44);
btnAdd.Name = "btnAdd";
btnAdd.Size = new Size(114, 33);
btnAdd.TabIndex = 1;
btnAdd.Text = "添加";
btnAdd.UseVisualStyleBackColor = true;
//
// dataGridView1
//
dataGridView1.AllowUserToAddRows = false;
dataGridView1.AllowUserToDeleteRows = false;
dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
dataGridView1.Dock = DockStyle.Bottom;
dataGridView1.Location = new Point(0, 116);
dataGridView1.Name = "dataGridView1";
dataGridView1.ReadOnly = true;
dataGridView1.RowHeadersWidth = 51;
dataGridView1.Size = new Size(710, 392);
dataGridView1.TabIndex = 2;
//
// btnUpdate
//
btnUpdate.Location = new Point(374, 44);
btnUpdate.Name = "btnUpdate";
btnUpdate.Size = new Size(114, 33);
btnUpdate.TabIndex = 3;
btnUpdate.Text = "更新";
btnUpdate.UseVisualStyleBackColor = true;
//
// btnDelete
//
btnDelete.Location = new Point(513, 44);
btnDelete.Name = "btnDelete";
btnDelete.Size = new Size(114, 33);
btnDelete.TabIndex = 4;
btnDelete.Text = "删除";
btnDelete.UseVisualStyleBackColor = true;
//
// FrmMain
//
AcceptButton = btnAdd;
AutoScaleDimensions = new SizeF(9F, 20F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(710, 508);
Controls.Add(btnDelete);
Controls.Add(btnUpdate);
Controls.Add(dataGridView1);
Controls.Add(btnAdd);
Controls.Add(txtNickName);
FormBorderStyle = FormBorderStyle.FixedSingle;
Name = "FrmMain";
StartPosition = FormStartPosition.CenterScreen;
Text = "主窗口";
Load += FrmMain_Load;
((System.ComponentModel.ISupportInitialize)dataGridView1).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private TextBox txtNickName;
private Button btnAdd;
private DataGridView dataGridView1;
private Button btnUpdate;
private Button btnDelete;
}
}