如何在具有分配的DataSource的DataGridView中启用排序? [英] How do you enable Sorting in a DataGridView with an assigned DataSource?

查看:40
本文介绍了如何在具有分配的DataSource的DataGridView中启用排序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

On several recommendations, I started to assign a DataSource to my DataGridView instead of using DataGridView.Rows.Add(...). This is convenient since my data source is already a big list which doesn't change (much). However, when I use the DataSource assignment, it becomes impossible to sort the columns.

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; 
    }
}

我还尝试用 BindingList< Person> BindingSource 替换 List< Person> ,但这似乎无关紧要.我还尝试添加自定义分类器:

I also tried to replace List<Person> by BindingList<Person> and by BindingSource, but none of that seems to matter. I also tried adding a custom sorter:

this.SortCompare += MyGridView_SortCompare;

private void MyGridView_SortCompare(object sender, EventArgs e)
{
    /* ...Compare method...*/
}

但是事情甚至没有被调用.还有其他方法可以对数据源进行排序吗?

but the thing doesn't even get called. Is there some other way to enable sorting with a DataSource?

注意:请注意,我的DataSource不是(不一定)是SQL,而是任何 List .

Note: Note that my DataSource is not (necessarily) an SQL one, but just any List.

推荐答案

您需要将数据源强制转换为支持排序的列表(IBindingList和IBindingListView),然后即可使用.网络上有很多示例,这是我过去使用的示例:

You need to coerce your datasource into a list that supports sorting (IBindingList and IBindingListView), and then it will work out of the box. There are lots of examples on the web, this is the one I've used in the past:

// 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;
    }
}

这篇关于如何在具有分配的DataSource的DataGridView中启用排序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆