欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

C# WINFORM開發可點擊列頭排序的ListView控件

admin
2024年10月9日 7:49 本文熱度 609

在Windows Forms應用程序中,ListView是一個非常實用的控件,用于顯示數據列表。但默認情況下,ListView并不支持點擊列頭進行排序,并增加了單元格設置顏色。本文將介紹如何開發一個可點擊列頭排序的ListView控件。

1. 創建自定義比較器

ListViewItemSorter?類是一個用于排序 ListView 控件中項目的自定義比較器。它實現了?IComparer<ListViewItem>?接口,可以按照指定的列、排序順序和數據類型對 ListViewItem 進行排序。

public class ListViewItemSorter : IComparer<ListViewItem>{ ? ?private int _columnIndex; ? ?private SortOrder _sortOrder; ? ?private ColumnDataType _dataType;
? ?public ListViewItemSorter(int columnIndex, SortOrder sortOrder, ColumnDataType dataType){ ? ? ? ?_columnIndex = columnIndex; ? ? ? ?_sortOrder = sortOrder; ? ? ? ?_dataType = dataType; ? ?}
? ?public int Compare(ListViewItem x, ListViewItem y){ ? ? ? ?string textX = x.SubItems[_columnIndex].Text; ? ? ? ?string textY = y.SubItems[_columnIndex].Text;
? ? ? ?int result;
? ? ? ?switch (_dataType) ? ? ? ?{ ? ? ? ? ? ?case ColumnDataType.Number: ? ? ? ? ? ? ? ?if (double.TryParse(textX, out double numX) && double.TryParse(textY, out double numY)) ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ?result = numX.CompareTo(numY); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?else ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ?result = string.Compare(textX, textY, StringComparison.OrdinalIgnoreCase); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case ColumnDataType.Date: ? ? ? ? ? ? ? ?if (DateTime.TryParse(textX, out DateTime dateX) && DateTime.TryParse(textY, out DateTime dateY)) ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ?result = dateX.CompareTo(dateY); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?else ? ? ? ? ? ? ? ?{ ? ? ? ? ? ? ? ? ? ?result = string.Compare(textX, textY, StringComparison.OrdinalIgnoreCase); ? ? ? ? ? ? ? ?} ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case ColumnDataType.Text: ? ? ? ? ? ?default: ? ? ? ? ? ? ? ?result = string.Compare(textX, textY, StringComparison.OrdinalIgnoreCase); ? ? ? ? ? ? ? ?break; ? ? ? ?}
? ? ? ?return _sortOrder == SortOrder.Ascending ? result : -result; ? ?}}

  1. 構造函數接受三個參數:

    • columnIndex:要排序的列的索引

    • sortOrder:排序順序(升序或降序)

    • dataType:列數據的類型(數字、日期或文本)

  2. Compare?方法實現了實際的比較邏輯:

    • 對于數字類型,嘗試將文本轉換為 double 進行比較

    • 對于日期類型,嘗試將文本轉換為 DateTime 進行比較

    • 對于文本類型或無法轉換的情況,使用字符串比較

    • 根據指定的列索引獲取要比較的文本

    • 根據數據類型進行相應的比較:

  3. 比較結果會根據指定的排序順序進行調整(升序或降序)

2. 重寫SortableVirtualListView

SortableVirtualListView 類是一個擴展的 ListView 控件,它提供了高效的大數據集處理和排序功能。

public class SortableVirtualListView : ListView{ ? ?private ColumnHeader _sortedColumn = null; ? ?private SortOrder _sortOrder = SortOrder.None; ? ?private List<ListViewItem> _items = new List<ListViewItem>(); ? ?private List<int> _sortedIndices = new List<int>(); ? ?private Dictionary<int, ColumnDataType> _columnTypes = new Dictionary<int, ColumnDataType>(); ? ?private const int MaxSortItems = 100000;
? ?private ProgressBar _progressBar; ? ?private BackgroundWorker _backgroundWorker; ? ?public event EventHandler DataLoadCompleted;
? ?public SortableVirtualListView() ? ?{ ? ? ? ?this.DoubleBuffered = true; ? ? ? ?this.VirtualMode = true; ? ? ? ?this.VirtualListSize = 0;
? ? ? ?InitializeProgressBar(); ? ? ? ?InitializeBackgroundWorker(); ? ?}
? ?protected override void OnRetrieveVirtualItem(RetrieveVirtualItemEventArgs e) ? ?{ ? ? ? ?if (e.ItemIndex >= 0 && e.ItemIndex < _items.Count) ? ? ? ?{ ? ? ? ? ? ?int actualIndex = _sortedIndices.Count > e.ItemIndex ? _sortedIndices[e.ItemIndex] : e.ItemIndex; ? ? ? ? ? ?e.Item = _items[actualIndex]; ? ? ? ?} ? ?}
? ?private void InitializeProgressBar() ? ?{ ? ? ? ?_progressBar = new ProgressBar ? ? ? ?{ ? ? ? ? ? ?Dock = DockStyle.Bottom, ? ? ? ? ? ?Visible = false, ? ? ? ? ? ?Height = 20 ? ? ? ?}; ? ? ? ?this.Controls.Add(_progressBar); ? ?}
? ?private void InitializeBackgroundWorker() ? ?{ ? ? ? ?_backgroundWorker = new BackgroundWorker ? ? ? ?{ ? ? ? ? ? ?WorkerReportsProgress = true, ? ? ? ? ? ?WorkerSupportsCancellation = true ? ? ? ?}; ? ? ? ?_backgroundWorker.DoWork += BackgroundWorker_DoWork; ? ? ? ?_backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged; ? ? ? ?_backgroundWorker.RunWorkerCompleted += BackgroundWorker_RunWorkerCompleted; ? ?}
? ?public void LoadItems(IEnumerable<ListViewItem> items) ? ?{ ? ? ? ?if (_backgroundWorker.IsBusy) ? ? ? ?{ ? ? ? ? ? ?_backgroundWorker.CancelAsync(); ? ? ? ?} ? ? ? ?_progressBar.Visible = true; ? ? ? ?_backgroundWorker.RunWorkerAsync(items); ? ?}
? ?private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e) ? ?{ ? ? ? ?var items = (IEnumerable<ListViewItem>)e.Argument; ? ? ? ?List<ListViewItem> loadedItems = new List<ListViewItem>(); ? ? ? ?int totalItems = items.Count(); ? ? ? ?int count = 0;
? ? ? ?foreach (var item in items) ? ? ? ?{ ? ? ? ? ? ?if (_backgroundWorker.CancellationPending) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?e.Cancel = true; ? ? ? ? ? ? ? ?return; ? ? ? ? ? ?}
? ? ? ? ? ?loadedItems.Add(item); ? ? ? ? ? ?count++;
? ? ? ? ? ?if (count % 1000 == 0 || count == totalItems) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?int progressPercentage = (int)((double)count / totalItems * 100); ? ? ? ? ? ? ? ?_backgroundWorker.ReportProgress(progressPercentage); ? ? ? ? ? ?} ? ? ? ?}
? ? ? ?e.Result = loadedItems; ? ?}
? ?private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) ? ?{ ? ? ? ?_progressBar.Value = e.ProgressPercentage; ? ?}
? ?private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) ? ?{ ? ? ? ?if (!e.Cancelled && e.Error == null) ? ? ? ?{ ? ? ? ? ? ?SetItems((List<ListViewItem>)e.Result); ? ? ? ?}
? ? ? ?_progressBar.Visible = false; ? ? ? ?DataLoadCompleted?.Invoke(this, EventArgs.Empty); ? ?}

? ?public void SetColumnDataType(int columnIndex, ColumnDataType dataType) ? ?{ ? ? ? ?_columnTypes[columnIndex] = dataType; ? ?}
? ?protected override void OnColumnClick(ColumnClickEventArgs e) ? ?{ ? ? ? ?base.OnColumnClick(e);
? ? ? ?ColumnHeader clickedColumn = this.Columns[e.Column];
? ? ? ?if (_sortedColumn == null) ? ? ? ?{ ? ? ? ? ? ?_sortOrder = SortOrder.Ascending; ? ? ? ?} ? ? ? ?else if (_sortedColumn == clickedColumn) ? ? ? ?{ ? ? ? ? ? ?_sortOrder = _sortOrder == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending; ? ? ? ?} ? ? ? ?else ? ? ? ?{ ? ? ? ? ? ?_sortOrder = SortOrder.Ascending; ? ? ? ?}
? ? ? ?_sortedColumn = clickedColumn; ? ? ? ?ColumnDataType dataType = _columnTypes.ContainsKey(e.Column) ? _columnTypes[e.Column] : ColumnDataType.Text;
? ? ? ?SortItems(e.Column, _sortOrder, dataType); ? ? ? ?this.Refresh();
? ? ? ?UpdateColumnHeaders(); ? ?}
? ?private void SortItems(int columnIndex, SortOrder sortOrder, ColumnDataType dataType) ? ?{ ? ? ? ?// 使用 LINQ 對索引進行排序,而不是對實際項目進行排序 ? ? ? ? ?IEnumerable<int> query = Enumerable.Range(0, _items.Count);
? ? ? ?switch (dataType) ? ? ? ?{ ? ? ? ? ? ?case ColumnDataType.Number: ? ? ? ? ? ? ? ?query = sortOrder == SortOrder.Ascending ? ? ? ? ? ? ? ? ? ?? query.OrderBy(i => GetDoubleValue(_items[i].SubItems[columnIndex].Text)) ? ? ? ? ? ? ? ? ? ?: query.OrderByDescending(i => GetDoubleValue(_items[i].SubItems[columnIndex].Text)); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case ColumnDataType.Date: ? ? ? ? ? ? ? ?query = sortOrder == SortOrder.Ascending ? ? ? ? ? ? ? ? ? ?? query.OrderBy(i => GetDateTimeValue(_items[i].SubItems[columnIndex].Text)) ? ? ? ? ? ? ? ? ? ?: query.OrderByDescending(i => GetDateTimeValue(_items[i].SubItems[columnIndex].Text)); ? ? ? ? ? ? ? ?break; ? ? ? ? ? ?case ColumnDataType.Text: ? ? ? ? ? ?default: ? ? ? ? ? ? ? ?query = sortOrder == SortOrder.Ascending ? ? ? ? ? ? ? ? ? ?? query.OrderBy(i => _items[i].SubItems[columnIndex].Text) ? ? ? ? ? ? ? ? ? ?: query.OrderByDescending(i => _items[i].SubItems[columnIndex].Text); ? ? ? ? ? ? ? ?break; ? ? ? ?}
? ? ? ?_sortedIndices = query.Take(MaxSortItems).ToList(); ? ?}
? ?private double GetDoubleValue(string text) ? ?{ ? ? ? ?return double.TryParse(text, out double result) ? result : double.MinValue; ? ?}
? ?private DateTime GetDateTimeValue(string text) ? ?{ ? ? ? ?return DateTime.TryParse(text, out DateTime result) ? result : DateTime.MinValue; ? ?}
? ?public void SetItems(List<ListViewItem> items) ? ?{ ? ? ? ?_items = items; ? ? ? ?_sortedIndices = Enumerable.Range(0, Math.Min(items.Count, MaxSortItems)).ToList(); ? ? ? ?this.VirtualListSize = items.Count; ? ? ? ?this.Refresh(); ? ?}
? ?private void UpdateColumnHeaders() ? ?{ ? ? ? ?foreach (ColumnHeader column in this.Columns) ? ? ? ?{ ? ? ? ? ? ?if (column == _sortedColumn) ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?column.Text = column.Text.TrimEnd('▲', '▼') + (_sortOrder == SortOrder.Ascending ? " ▲" : " ▼"); ? ? ? ? ? ?} ? ? ? ? ? ?else ? ? ? ? ? ?{ ? ? ? ? ? ? ? ?column.Text = column.Text.TrimEnd('▲', '▼'); ? ? ? ? ? ?} ? ? ? ?} ? ?}}
public enum ColumnDataType{ ? ?Text, ? ?Number, ? ?Date}

  • 虛擬模式:使用 ListView 的虛擬模式來處理大量數據,提高性能。

  • 異步數據加載:

    • 使用 BackgroundWorker 在后臺異步加載數據。

    • 包含進度條顯示加載進度。

    • 提供 DataLoadCompleted 事件通知數據加載完成。

  • 自定義排序:

    • 支持點擊列頭進行排序。

    • 可以為每列指定數據類型(文本、數字、日期)。

    • 使用索引排序而不是直接排序項目,提高大數據集的排序效率。

  • 列頭排序指示:

    • 在列頭顯示排序方向(升序/降序)。

  • 性能優化:

    • 使用雙緩沖減少閃爍。

    • 限制最大排序項目數量(MaxSortItems)以處理超大數據集。

使用控件

public partial class Form1 : Form{ ? ?private SortableVirtualListView sortableListView; ? ?private const int ItemCount = 1000000; // 100萬條數據 ?
? ?public Form1() ? ?{ ? ? ? ?InitializeComponent(); ? ? ? ?InitializeSortableListView(); ? ? ? ?LoadLargeDataSet(); ? ?}
? ?private void InitializeSortableListView() ? ?{ ? ? ? ?sortableListView = new SortableVirtualListView ? ? ? ?{ ? ? ? ? ? ?Dock = DockStyle.Fill, ? ? ? ? ? ?View = View.Details, ? ? ? ? ? ?FullRowSelect = true, ? ? ? ? ? ?GridLines = true ? ? ? ?};
? ? ? ?sortableListView.Columns.Add("ID", 80); ? ? ? ?sortableListView.Columns.Add("Name", 150); ? ? ? ?sortableListView.Columns.Add("Value", 100); ? ? ? ?sortableListView.Columns.Add("Date", 120);
? ? ? ?sortableListView.SetColumnDataType(0, ColumnDataType.Number); ? ? ? ?sortableListView.SetColumnDataType(1, ColumnDataType.Text); ? ? ? ?sortableListView.SetColumnDataType(2, ColumnDataType.Number); ? ? ? ?sortableListView.SetColumnDataType(3, ColumnDataType.Date);
? ? ? ?sortableListView.DataLoadCompleted += SortableListView_DataLoadCompleted;
? ? ? ?this.Controls.Add(sortableListView);
? ?}
? ?private void LoadLargeDataSet() ? ?{ ? ? ? ?Random random = new Random(); ? ? ? ?DateTime startDate = new DateTime(2000, 1, 1);
? ? ? ?var items = Enumerable.Range(0, ItemCount).Select(i => new ListViewItem(new[] ? ? ? ?{ ? ? ? ?i.ToString(), ? ? ? ?$"Item {i}", ? ? ? ?random.Next(1, 1000).ToString(), ? ? ? ?startDate.AddDays(random.Next(0, 8000)).ToString("yyyy-MM-dd") ? ?}));
? ? ? ?sortableListView.LoadItems(items); ? ?} ? ?private void SortableListView_DataLoadCompleted(object sender, EventArgs e) ? ?{ ? ? ? ?this.Text = "Large Data Set Loaded"; ? ?}
}

?

結論

通過以上步驟,我們成功創建了一個可點擊列頭排序的ListView控件。這個自定義控件不僅支持點擊列頭進行排序,還能顯示排序方向,極大地提高了用戶體驗。您可以根據需要進一步擴展這個控件,例如添加自定義的排序算法或者支持不同數據類型的排序。


該文章在 2024/10/9 12:29:20 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved