首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

OutlookGrid:繼承 DataGridView 實現 Outlook 樣式分組與排序的開源控件

     編輯:關於C#

專案簡介

OutlookGrid 是一個繼承自 DataGridView 的開源 WinForms 控件,提供類似 Outlook 2003/2007 的資料分組、排序、摺疊/展開功能。專案採用 C# 2.0 / VS 2005 開發,原始碼開放,可自由修改擴展。

核心特性

  • 分組模板化:透過 GroupTemplate 屬性支援預設分組、字母分組、日期分組(今日/本週/本月)等多種分組邏輯。
  • 雙模式資料綁定:支援 DataSet/DataTable 綁定模式,也支援非綁定模式手動加入 OutlookGridRow。
  • 排序與分組分離:排序由 IComparer 實作(DataRowComparer、OutlookGridRowComparer),分組由 IOutlookGridGroup 介面實作。
  • 摺疊/展開動畫:群組列可點擊摺疊/展開,子列透過重寫 GetState 隱藏而非 Visible=false,避免基類重繪問題。

快速上手:資料綁定模式

// 1. 準備資料
var ds = new DataSet();
ds.ReadXml("invoices.xml"); // 包含 "invoice" Table

// 2. 綁定
outlookGrid1.BindData(ds, "invoice");

// 3. 設定分組模板(字母分組)
outlookGrid1.GroupTemplate = new OutlookGridAlphabeticGroup();
outlookGrid1.GroupTemplate.Column = outlookGrid1.Columns["CustomerName"];
outlookGrid1.GroupTemplate.Column.Collapsed = true; // 預設摺疊

// 4. 排序並自動分組
outlookGrid1.Sort(new DataRowComparer(outlookGrid1.Columns["CustomerName"].Index, SortOrder.Ascending));

非綁定模式:手動建立資料

outlookGrid1.BindData(null, null); // 清除綁定

outlookGrid1.Columns.Add("colId", "ID");
outlookGrid1.Columns.Add("colName", "名稱");
outlookGrid1.Columns.Add("colDate", "日期");

// 必須使用 OutlookGridRow
var row1 = new OutlookGridRow();
row1.CreateCells(outlookGrid1, 1, "客戶 A", DateTime.Today);
outlookGrid1.Rows.Add(row1);

var row2 = new OutlookGridRow();
row2.CreateCells(outlookGrid1, 2, "客戶 B", DateTime.Today.AddDays(-1));
outlookGrid1.Rows.Add(row2);

// 非綁定模式排序:直接指定欄位索引
outlookGrid1.GroupTemplate = new OutlookGridDefaultGroup();
outlookGrid1.GroupTemplate.Column = outlookGrid1.Columns[1];
outlookGrid1.Sort(outlookGrid1.Columns[1], SortOrder.Ascending);

架構設計亮點

類別職責
OutlookGrid主控件,管理 RowTemplate、DataSourceManager、GroupTemplate,重寫 Paint/排序/滾動事件
OutlookGridRow擴充 IsGroupRow、Group 屬性,重寫 Paint/GetState 實現群組列外觀與摺疊邏輯
IOutlookGridGroup / OutlookGridDefaultGroup / OutlookGridAlphabeticGroup / OutlookGridDateTimeGroup分組邏輯封裝:CompareTo 判斷列屬於哪群組,Text 決定顯示文字,Clone 支援動態建立群組實例
DataSourceManager抽象層:索引綁定/非綁定資料,提供統一存取介面,支援將 OutlookGrid 自身作為資料來源

已知限制(原作者說明)

  • ❌ 不支援巢狀分組(多層群組)。
  • ❌ 變更 DataGridView 樣式(如 EnableHeadersVisualStyles)可能導致群組列繪製異常。
  • ❌ 群組列文字顏色固定黑色,需修改 OutlookGridRow.Paint 自行調整。
  • ❌ 未測試 VirtualMode,大量資料(>10萬列)效能未驗證。
  • ❌ 資料綁定模式下編輯不會回寫資料來源,需自行實作 CellValuePushed 等事件。
  • ❌ 群組列不觸發所有基類事件(如 DoubleClick 已重寫作為摺疊/展開觸發)。

擴展範例:自訂日期分組(今日/昨日/本週/更早)

public class OutlookGridCustomDateGroup : IOutlookGridGroup
{
    public DataGridViewColumn Column { get; set; }
    public bool Collapsed { get; set; }

    public int CompareTo(object value)
    {
        if (value == null || value == DBNull.Value) return -1;
        DateTime dt = Convert.ToDateTime(value);
        DateTime today = DateTime.Today;

        if (dt.Date == today) return 0;           // 今日
        if (dt.Date == today.AddDays(-1)) return 1; // 昨日
        if (dt >= today.AddDays(-(int)today.DayOfWeek)) return 2; // 本週
        if (dt.Month == today.Month && dt.Year == today.Year) return 3; // 本月
        return 4; // 更早
    }

    public string Text { get; }
    public object GroupValue { get; set; }

    public object Clone() => new OutlookGridCustomDateGroup { Column = Column, Collapsed = Collapsed };
}

總結

OutlookGrid 以極少代碼實現了 DataGridView 缺乏的分組功能,架構清晰、擴展性佳。雖有已知限制,但對於中小型專案、內部工具、快速原型開發,已足夠勝任。若需生產級大量資料、巢狀分組、雙向綁定編輯,建議評估商用控件(DevExpress XtraGrid、Telerik RadGridView)或自行基於 VirtualMode 重寫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved