DataView 提供排序、篩選、編輯狀態追蹤,配合 DataTable 關聯關係 (DataRelation) 可實現主從聯動、去重下拉選單、跨表彙總等進階 UI 互動,且完全在記憶體中運作,無需重查資料庫。本文透過完整 WinForm 範例示範三大實用技巧。
comboBox1 選人員、comboBox2 顯示該人員板塊、dataGridView1 全部資料、dataGridView2 篩選後資料、dataGridView3 人員彙總 (總積分、板塊數)using System;
using System.Data;
using System.Windows.Forms;
public partial class Form1 : Form
{
private readonly DataTable _dt = new("Table1");
private readonly DataSet _ds = new();
public Form1()
{
InitializeComponent();
InitData();
SetupBinding();
}
private void InitData()
{
_dt.Columns.Add("ID", typeof(string));
_dt.Columns.Add("板塊", typeof(string));
_dt.Columns.Add("積分", typeof(int));
_ds.Tables.Add(_dt);
Add("jinjazz", "delphi", 50000);
Add("jinjazz", "Sqlserver", 10000);
Add("jinjazz", ".net", 20000);
Add("zjcxc", "Sqlserver", 900000);
Add("zjcxc", "vb", 10000);
Add("zswang", "delphi", 70000);
Add("zswang", ".net", 30000);
}
private void Add(string id, string catalog, int score)
{
var r = _dt.NewRow();
r["ID"] = id; r["板塊"] = catalog; r["積分"] = score;
_dt.Rows.Add(r);
}
private void SetupBinding()
{
// 1. ComboBox1:去重 ID 列表
comboBox1.DataSource = _dt.DefaultView.ToTable(true, "ID"); // distinct
comboBox1.DisplayMember = "ID";
// 2. ComboBox2:板塊 (將透過 RowFilter 聯動)
comboBox2.DataSource = new DataView(_dt);
comboBox2.DisplayMember = "板塊";
// 3. GridView1:全部資料
dataGridView1.DataSource = _dt;
// 4. GridView2:篩選檢視 (同步 ComboBox1)
dataGridView2.DataSource = new DataView(_dt);
// 5. 聯動:ComboBox1 選擇變更 -> 篩選 GridView2 & ComboBox2
comboBox1.SelectedIndexChanged += (s, e) =>
{
string id = comboBox1.Text;
string filter = $"ID = '{id}'";
((DataView)comboBox2.DataSource).RowFilter = filter;
((DataView)dataGridView2.DataSource).RowFilter = filter;
};
// 6. 彙總表:利用 DataRelation + Expression 計算欄位
DataTable summary = _dt.DefaultView.ToTable(true, "ID"); // distinct ID
summary.TableName = "Summary";
_ds.Tables.Add(summary);
var rel = new DataRelation("Rel", summary.Columns["ID"], _dt.Columns["ID"]);
_ds.Relations.Add(rel);
summary.Columns.Add("總積分", typeof(int), "Sum(Child(Rel).積分)");
summary.Columns.Add("板塊數", typeof(int), "Count(Child(Rel).板塊)");
dataGridView3.DataSource = summary;
}
}
| 技巧 | 核心 API | 說明 |
|---|---|---|
| 去重下拉選單 | DataView.ToTable(true, columns...) | 第一參數 `true` 開啟 Distinct,回傳新 DataTable 可直接繫結 |
| 多控制項同步篩選 | DataView.RowFilter | 共用同一 DataView 實例或各自建立 View,設定相同 Filter 即時生效 |
| 主從關聯彙總 | DataRelation + DataColumn.Expression | `Sum(Child(Rel).Column)`、`Count(Child(Rel).Column)` 自動計算,無需手寫迴圈 |
| Expression 語法 | DataColumn.Expression | 支援 `Sum`、`Count`、`Avg`、`Min`、`Max`、`Parent(Rel).Col` 等聚合與導航 |
DataRelation,Expression 可鏈式 `Child(Rel1).Child(Rel2).Col`。BindingSource 共用同一 DataView,編輯立即反映所有繫結控制項。DataView.FindRows 或預先索引。DataView + DataRelation + Expression 是 ADO.NET 記憶體資料操作的「三板斧」,善用可大幅減少資料庫往返、簡化 UI 同步邏輯、實現豐富的主從彙總介面。現代專案若使用 Entity Framework,可考慮將邏輯下推至 LINQ to Entities 或資料庫 View,但離線場景 (報表、匯入預覽、行動裝置快取) 此組合依然極具價值。