首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

ListView 控制項多欄點擊排序完整實作

     編輯:VC 教學

ListView 的報表檢視 (vsReport) 常用於顯示多欄資料。Windows 檔案總管支援點擊欄標標題排序,但 BCB 預設 SortType 僅支援依首欄排序。本文實作完整的多欄點擊排序功能:奇數次點擊降序、偶數次升序,支援主欄與子欄排序。

環境準備

  1. 放置 TListView,命名 ListView1。
  2. 設 ViewStyle = vsReport,SortType = stNone(關閉內建排序)。
  3. 右鍵選 Columns Editor 新增欄位,Items Editor 新增測試資料。
  4. 為 ListView1 建立 OnColumnClick 事件處理函式。

核心排序邏輯


void __fastcall TForm1::ListView1ColumnClick(TObject *Sender, TListColumn *Column) {
    static bool descending = true; // 靜態變數記錄排序方向
    descending = !descending;      // 每次點擊切換

    int colIndex = Column->Index;  // 點擊的欄索引
    int itemCount = ListView1->Items->Count;

    // 新增臨時項目作為交換緩衝
    ListView1->Items->Add();
    int tempIndex = itemCount;     // 臨時項目索引

    // 比較函式:依欄索引取得比較字串
    auto GetCompareText = [&](int itemIdx) -> AnsiString {
        if (colIndex == 0)
            return ListView1->Items->Item[itemIdx]->Caption;
        else
            return ListView1->Items->Item[itemIdx]->SubItems->Strings[colIndex - 1];
    };

    // 簡單氣泡排序(示範用,大量資料建議改用 std::sort + 索引陣列)
    for (int i = 0; i < itemCount - 1; i++) {
        for (int j = i + 1; j < itemCount; j++) {
            AnsiString textI = GetCompareText(i);
            AnsiString textJ = GetCompareText(j);
            bool needSwap = descending ? (textI > textJ) : (textI < textJ);
            if (needSwap) {
                // 利用臨時項目交換
                TListItem *temp = ListView1->Items->Item[tempIndex];
                temp->Assign(ListView1->Items->Item[i]);
                ListView1->Items->Item[i]->Assign(ListView1->Items->Item[j]);
                ListView1->Items->Item[j]->Assign(temp);
            }
        }
    }

    ListView1->Items->Delete(tempIndex); // 移除臨時項目
}

關鍵點解析

  • 靜態變數 descending 保持排序方向在點擊間持久。
  • 主欄 vs 子欄:Caption 為第 0 欄,SubItems->Strings[n] 為第 n+1 欄。
  • 交換策略:新增一個臨時 TListItem 做緩衝,利用 Assign 複製整列資料(含圖示、子欄等),避免手動逐欄交換。
  • 排序演算法:範例用氣泡排序易懂但 O(n²)。實務上應建立索引陣列 std::vector idx,配合 std::sort 自訂比較函式,最後按排序後索引重建 ListView 項目順序,效能大幅提升。

數值/日期排序擴充

字串比較無法正確排序數值(如 "100" < "20")。解決方案:

  • 比較前嘗試 StrToInt/StrToFloat/StrToDateTime 轉換,成功則數值/日期比較,失敗退回字串比較。
  • 或在資料載入時,將原始數值/日期儲存於 TListItem->Data 指標指向的結構中,排序時直接比較型別化資料。

完善建議

  • 在欄標顯示排序指示器(▲/▼),需處理 WM_NOTIFY / HDN_ITEMCLICK 並設定 HDF_SORTUP/DOWN 標誌。
  • 大量資料時啟用 ListView1->Items->BeginUpdate()/EndUpdate() 防止閃爍。
  • 考慮將排序邏輯封裝為通用工具類,支援多欄複合排序。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved