C# 如何在具有指定数据源的DataGridView中启用排序?

C# 如何在具有指定数据源的DataGridView中启用排序?,c#,winforms,datagridview,gridview-sorting,C#,Winforms,Datagridview,Gridview Sorting,根据一些建议,我开始将一个数据源分配给我的DataGridView,而不是使用DataGridView.Rows.Add(…)。这很方便,因为我的数据源已经是一个很大的列表,而且变化不大。但是,当我使用DataSource赋值时,就无法对列进行排序 class MyGridView : DataGridView { private List<Person> m_personList; private class Person { public

根据一些建议,我开始将一个
数据源
分配给我的
DataGridView
,而不是使用
DataGridView.Rows.Add(…)
。这很方便,因为我的数据源已经是一个很大的列表,而且变化不大。但是,当我使用
DataSource
赋值时,就无法对列进行排序

class MyGridView : DataGridView
{
    private List<Person> m_personList;

    private class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Person(string first, string last)
        {
            FirstName = first;
            LastName = last;
        }
    }

    public MyGridView()
    {
         /* ...initialise stuff... */
         m_personList.Add(new Person("Kate", "Smith"));
         m_personList.Add(new Person("Bill", "Davids"));
         m_personList.Add(new Person("Ann", "Roth"));

         this.DataSource = m_personList; 
    }
}
但这东西甚至没人叫。是否有其他方法可以使用数据源进行排序


注意:请注意,我的数据源(不一定)是SQL数据源,而只是任何
列表
您需要将您的数据源强制转换为支持排序的列表(IBindingList和IBindingListView),然后它将立即运行。网上有很多例子,这是我过去用过的例子:

// usage:
// var sortableList = new SortableList(m_personList);
// dgv.DataSource = m_sortableList; 


/// <summary>
///  Suitable for binding to DataGridView when column sorting is required
/// </summary>
/// <typeparam name="T"></typeparam>
public class SortableList<T> : BindingList<T>, IBindingListView
{
    private PropertyComparerCollection<T> sorts;

    public SortableList()
    {
    }

    public SortableList(IEnumerable<T> initialList)
    {
        foreach (T item in initialList)
        {
            this.Add(item);
        }
    }

    public SortableList<T> ApplyFilter(Func<T, bool> func)
    {
        SortableList<T> newList = new SortableList<T>();
        foreach (var item in this.Where(func))
        {
            newList.Add(item);
        }

        return newList;
    }

    protected override bool IsSortedCore
    {
        get { return this.sorts != null; }
    }

    protected override bool SupportsSortingCore
    {
        get { return true; }
    }

    protected override ListSortDirection SortDirectionCore
    {
        get
        {
            return this.sorts == null
                       ? ListSortDirection.Ascending
                       : this.sorts.PrimaryDirection;
        }
    }

    protected override PropertyDescriptor SortPropertyCore
    {
        get
        {
            return this.sorts == null ? null : this.sorts.PrimaryProperty;
        }
    }

    public void ApplySort(ListSortDescriptionCollection
                              sortCollection)
    {
        bool oldRaise = RaiseListChangedEvents;
        RaiseListChangedEvents = false;
        try
        {
            PropertyComparerCollection<T> tmp
                = new PropertyComparerCollection<T>(sortCollection);
            List<T> items = new List<T>(this);
            items.Sort(tmp);
            int index = 0;
            foreach (T item in items)
            {
                SetItem(index++, item);
            }
            this.sorts = tmp;
        }
        finally
        {
            RaiseListChangedEvents = oldRaise;
            ResetBindings();
        }
    }

    public bool Exists(Predicate<T> func)
    {
        return new List<T>(this).Exists(func);
    }

    string IBindingListView.Filter
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    void IBindingListView.RemoveFilter()
    {
        throw new NotImplementedException();
    }

    ListSortDescriptionCollection IBindingListView.SortDescriptions
    {
        get { return (this.sorts == null ? null : this.sorts.Sorts); }
    }

    bool IBindingListView.SupportsAdvancedSorting
    {
        get { return true; }
    }

    bool IBindingListView.SupportsFiltering
    {
        get { return false; }
    }

    protected override void RemoveSortCore()
    {
        this.sorts = null;
    }

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
    {
        ListSortDescription[] arr = { new ListSortDescription(prop, direction) };
        ApplySort(new ListSortDescriptionCollection(arr));
    }
}

public class PropertyComparerCollection<T> : IComparer<T>
{
    private readonly PropertyComparer<T>[] comparers;

    private readonly ListSortDescriptionCollection sorts;

    public PropertyComparerCollection(ListSortDescriptionCollection
                                          sorts)
    {
        if (sorts == null)
        {
            throw new ArgumentNullException("sorts");
        }
        this.sorts = sorts;
        List<PropertyComparer<T>> list = new
            List<PropertyComparer<T>>();

        foreach (ListSortDescription item in sorts)
        {
            list.Add(new PropertyComparer<T>(item.PropertyDescriptor,
                                             item.SortDirection == ListSortDirection.Descending));
        }

        this.comparers = list.ToArray();
    }

    public ListSortDescriptionCollection Sorts
    {
        get { return this.sorts; }
    }

    public PropertyDescriptor PrimaryProperty
    {
        get
        {
            return this.comparers.Length == 0
                       ? null
                       : this.comparers[0].Property;
        }
    }

    public ListSortDirection PrimaryDirection
    {
        get
        {
            return this.comparers.Length == 0
                       ? ListSortDirection.Ascending
                       : this.comparers[0].Descending
                             ? ListSortDirection.Descending
                             : ListSortDirection.Ascending;
        }
    }

    int IComparer<T>.Compare(T x, T y)
    {
        int result = 0;
        foreach (PropertyComparer<T> t in this.comparers)
        {
            result = t.Compare(x, y);
            if (result != 0)
            {
                break;
            }
        }
        return result;
    }
}

public class PropertyComparer<T> : IComparer<T>
{
    private readonly bool descending;

    private readonly PropertyDescriptor property;

    public PropertyComparer(PropertyDescriptor property, bool descending)
    {
        if (property == null)
        {
            throw new ArgumentNullException("property");
        }

        this.descending = descending;
        this.property = property;
    }

    public bool Descending
    {
        get { return this.descending; }
    }

    public PropertyDescriptor Property
    {
        get { return this.property; }
    }

    public int Compare(T x, T y)
    {
        int value = Comparer.Default.Compare(this.property.GetValue(x),
                                             this.property.GetValue(y));
        return this.descending ? -value : value;
    }
}
//用法:
//var sortableList=新的sortableList(m_personList);
//dgv.DataSource=m_可排序列表;
/// 
///适用于在需要列排序时绑定到DataGridView
/// 
/// 
公共类SortableList:BindingList,IBindingListView
{
私人财产比较收集类别;
公共可排序列表()
{
}
公共可排序列表(IEnumerable initialList)
{
foreach(初始列表中的T项)
{
本条增加(项目);
}
}
公共可排序列表应用过滤器(Func Func)
{
SortableList newList=新的SortableList();
foreach(此.Where(func)中的变量项)
{
新建列表。添加(项);
}
返回newList;
}
受保护的覆盖布尔IsSortedCore
{
获取{返回this.sorts!=null;}
}
受保护的覆盖布尔支持SSortingCore
{
获取{return true;}
}
受保护的覆盖列表SORTDirection SortDirectionCore
{
得到
{
返回this.sorts==null
?ListSortDirection.升序
:this.sorts.PrimaryDirection;
}
}
受保护的重写属性描述符SortPropertyCore
{
得到
{
返回this.sorts==null?null:this.sorts.PrimaryProperty;
}
}
public void ApplySort(ListSortDescriptionCollection)
sortCollection)
{
bool oldRaise=RaiseListChangedEvents;
RaiseListChangedEvents=false;
尝试
{
属性比较收集tmp
=新财产比较收集(sortCollection);
列表项=新列表(本);
项目分类(tmp);
int指数=0;
foreach(项目中的T项目)
{
SetItem(index++,item);
}
this.sorts=tmp;
}
最后
{
RaiseListChangedEvents=oldRaise;
重置绑定();
}
}
公共布尔存在(谓词func)
{
返回新列表(此).Exists(func);
}
字符串IBindingListView.Filter
{
获取{抛出新的NotImplementedException();}
设置{抛出新的NotImplementedException();}
}
void IBindingListView.RemoveFilter()无效
{
抛出新的NotImplementedException();
}
ListSortDescriptionCollection IBindingListView.SortDescriptions
{
获取{return(this.sorts==null?null:this.sorts.sorts);}
}
bool IBindingListView.SupportsAdvancedSorting
{
获取{return true;}
}
bool-IBindingListView.supports过滤
{
获取{return false;}
}
受保护的覆盖void RemoveSortCore()
{
this.sorts=null;
}
受保护的覆盖无效ApplySortCore(PropertyDescriptor属性、ListSortDirection方向)
{
ListSortDescription[]arr={new ListSortDescription(prop,direction)};
ApplySort(新列表或描述集合(arr));
}
}
公共类属性比较集合:IComparer
{
私有只读属性Comparer[]比较器;
私有只读列表SortDescriptionCollection排序;
公共财产比较集合(列表或描述集合)
排序)
{
if(排序==null)
{
抛出新的异常(“排序”);
}
this.sorts=排序;
列表=新建
List();
foreach(排序中的ListSortDescription项)
{
列表。添加(新属性比较程序)(item.PropertyDescriptor,
item.SortDirection==ListSortDirection.Descending));
}
this.comparers=list.ToArray();
}
公共列表SortDescriptionCollection排序
{
获取{返回this.sorts;}
}
公共属性描述器PrimaryProperty
{
得到
{
返回this.comparers.Length==0
无效的
:this.comparers[0]。属性;
}
}
公共列表方向主方向
{
得到
{
返回this.comparers.Length==0
?ListSortDirection.升序
:this.comparers[0]。降序
?ListSortDirection.下降
:ListSortDirection.升序;
}
}
int IComparer.Compare(T x,T y)
{
int结果=0;
foreach(此.comparers中的PropertyComparer t)
{
结果=t.比较(x,y);
如果(结果!=0)
{
打破
}
}
返回结果;
}
}
公共类属性比较者:IComparer
{
私有只读布尔下降;
私有只读属性Descriptor属性;
公共属性比较程序(PropertyDescriptor属性,布尔递减)
{
if(属性==null)
{
抛出新的ArgumentNullException(“属性”);
}
这个。下降=下降;
th
// usage:
// var sortableList = new SortableList(m_personList);
// dgv.DataSource = m_sortableList; 


/// <summary>
///  Suitable for binding to DataGridView when column sorting is required
/// </summary>
/// <typeparam name="T"></typeparam>
public class SortableList<T> : BindingList<T>, IBindingListView
{
    private PropertyComparerCollection<T> sorts;

    public SortableList()
    {
    }

    public SortableList(IEnumerable<T> initialList)
    {
        foreach (T item in initialList)
        {
            this.Add(item);
        }
    }

    public SortableList<T> ApplyFilter(Func<T, bool> func)
    {
        SortableList<T> newList = new SortableList<T>();
        foreach (var item in this.Where(func))
        {
            newList.Add(item);
        }

        return newList;
    }

    protected override bool IsSortedCore
    {
        get { return this.sorts != null; }
    }

    protected override bool SupportsSortingCore
    {
        get { return true; }
    }

    protected override ListSortDirection SortDirectionCore
    {
        get
        {
            return this.sorts == null
                       ? ListSortDirection.Ascending
                       : this.sorts.PrimaryDirection;
        }
    }

    protected override PropertyDescriptor SortPropertyCore
    {
        get
        {
            return this.sorts == null ? null : this.sorts.PrimaryProperty;
        }
    }

    public void ApplySort(ListSortDescriptionCollection
                              sortCollection)
    {
        bool oldRaise = RaiseListChangedEvents;
        RaiseListChangedEvents = false;
        try
        {
            PropertyComparerCollection<T> tmp
                = new PropertyComparerCollection<T>(sortCollection);
            List<T> items = new List<T>(this);
            items.Sort(tmp);
            int index = 0;
            foreach (T item in items)
            {
                SetItem(index++, item);
            }
            this.sorts = tmp;
        }
        finally
        {
            RaiseListChangedEvents = oldRaise;
            ResetBindings();
        }
    }

    public bool Exists(Predicate<T> func)
    {
        return new List<T>(this).Exists(func);
    }

    string IBindingListView.Filter
    {
        get { throw new NotImplementedException(); }
        set { throw new NotImplementedException(); }
    }

    void IBindingListView.RemoveFilter()
    {
        throw new NotImplementedException();
    }

    ListSortDescriptionCollection IBindingListView.SortDescriptions
    {
        get { return (this.sorts == null ? null : this.sorts.Sorts); }
    }

    bool IBindingListView.SupportsAdvancedSorting
    {
        get { return true; }
    }

    bool IBindingListView.SupportsFiltering
    {
        get { return false; }
    }

    protected override void RemoveSortCore()
    {
        this.sorts = null;
    }

    protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
    {
        ListSortDescription[] arr = { new ListSortDescription(prop, direction) };
        ApplySort(new ListSortDescriptionCollection(arr));
    }
}

public class PropertyComparerCollection<T> : IComparer<T>
{
    private readonly PropertyComparer<T>[] comparers;

    private readonly ListSortDescriptionCollection sorts;

    public PropertyComparerCollection(ListSortDescriptionCollection
                                          sorts)
    {
        if (sorts == null)
        {
            throw new ArgumentNullException("sorts");
        }
        this.sorts = sorts;
        List<PropertyComparer<T>> list = new
            List<PropertyComparer<T>>();

        foreach (ListSortDescription item in sorts)
        {
            list.Add(new PropertyComparer<T>(item.PropertyDescriptor,
                                             item.SortDirection == ListSortDirection.Descending));
        }

        this.comparers = list.ToArray();
    }

    public ListSortDescriptionCollection Sorts
    {
        get { return this.sorts; }
    }

    public PropertyDescriptor PrimaryProperty
    {
        get
        {
            return this.comparers.Length == 0
                       ? null
                       : this.comparers[0].Property;
        }
    }

    public ListSortDirection PrimaryDirection
    {
        get
        {
            return this.comparers.Length == 0
                       ? ListSortDirection.Ascending
                       : this.comparers[0].Descending
                             ? ListSortDirection.Descending
                             : ListSortDirection.Ascending;
        }
    }

    int IComparer<T>.Compare(T x, T y)
    {
        int result = 0;
        foreach (PropertyComparer<T> t in this.comparers)
        {
            result = t.Compare(x, y);
            if (result != 0)
            {
                break;
            }
        }
        return result;
    }
}

public class PropertyComparer<T> : IComparer<T>
{
    private readonly bool descending;

    private readonly PropertyDescriptor property;

    public PropertyComparer(PropertyDescriptor property, bool descending)
    {
        if (property == null)
        {
            throw new ArgumentNullException("property");
        }

        this.descending = descending;
        this.property = property;
    }

    public bool Descending
    {
        get { return this.descending; }
    }

    public PropertyDescriptor Property
    {
        get { return this.property; }
    }

    public int Compare(T x, T y)
    {
        int value = Comparer.Default.Compare(this.property.GetValue(x),
                                             this.property.GetValue(y));
        return this.descending ? -value : value;
    }
}