使用 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;
}
}