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

WinForms DataGridView 綁定對象集合實現列排序完整指南

     編輯:關於.NET

早期 .NET 開發常用 DataSet/DataTable 作為數據源,DataGridView 綁定時原生支援點擊列標題排序。但隨著領域模型普及,改用 List<T> 或 BindingList<T> 綁定對象集合後,排序功能卻失效了。本文詳細講解如何透過繼承 BindingList<T> 並實作 IComparer<T>,為 WinForms 數據綁定恢復完整的列排序能力。

問題重現

// 實體類
public struct UserInfo
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Password { get; set; }
    public string Email { get; set; }
    public string Address { get; set; }
}

// 綁定代碼
var list = new BindingList<UserInfo>();
list.Add(new UserInfo { Id = "1", Name = "張三", ... });
list.Add(new UserInfo { Id = "2", Name = "李四", ... });
dataGridView1.DataSource = list; // 點擊列標題無反應

解決方案:自定義可排序 BindingList

1. 通用屬性比較器

public class ObjectPropertyComparer<T> : IComparer<T>
{
    private readonly PropertyDescriptor _property;
    private readonly ListSortDirection _direction;

    public ObjectPropertyComparer(PropertyDescriptor property, ListSortDirection direction)
    {
        _property = property;
        _direction = direction;
    }

    public int Compare(T x, T y)
    {
        object xVal = _property.GetValue(x);
        object yVal = _property.GetValue(y);

        int result;
        if (xVal is IComparable comparable)
        {
            result = comparable.CompareTo(yVal);
        }
        else if (xVal != null && yVal != null)
        {
            result = xVal.ToString().CompareTo(yVal.ToString());
        }
        else
        {
            result = 0;
        }

        return _direction == ListSortDirection.Ascending ? result : -result;
    }
}

2. 繼承 BindingList<T> 並重寫排序核心方法

public class SortableBindingList<T> : BindingList<T>
{
    private bool _isSorted;
    private PropertyDescriptor _sortProperty;
    private ListSortDirection _sortDirection;

    protected override bool SupportsSortingCore => true;
    protected override bool IsSortedCore => _isSorted;
    protected override PropertyDescriptor SortPropertyCore => _sortProperty;
    protected override ListSortDirection SortDirectionCore => _sortDirection;

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
    {
        var items = Items as List<T>;
        if (items != null)
        {
            var comparer = new ObjectPropertyComparer<T>(prop, direction);
            items.Sort(comparer);
            _isSorted = true;
            _sortProperty = prop;
            _sortDirection = direction;
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
        else
        {
            _isSorted = false;
        }
    }

    protected override void RemoveSortCore()
    {
        _isSorted = false;
        _sortProperty = null;
        _sortDirection = ListSortDirection.Ascending;
        OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }
}

使用方式

var sortableList = new SortableBindingList<UserInfo>();
sortableList.Add(new UserInfo { Id = "1", Name = "張三", ... });
sortableList.Add(new UserInfo { Id = "2", Name = "李四", ... });
dataGridView1.DataSource = sortableList; // 現在點擊列標題即可排序

進階補充

  • 多列排序:可擴展 ApplySortCore 接受 ListSortDescriptionCollection 實現多鍵排序。
  • 效能優化:大數據量時建議使用虛擬模式 (VirtualMode) 配合自定義排序邏輯。
  • Nullable 型別支援:比較器中需額外處理 Nullable<T> 的 HasValue 情況。

採用此模式,既保持了面向對象設計的純粹性,又獲得了與 DataTable 相媲美的 UI 交互體驗。

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