How to sort databound DataGridView column?

前端 未结 2 1481
情话喂你
情话喂你 2020-11-29 08:45

I know that there are a lot of questions on this topic. I have been through all of them but nothing seems to help.

How to sort by clicking on column header?

相关标签:
2条回答
  • 2020-11-29 09:24

    Here is the blog post that really really helped me.

    Presenting the SortableBindableList

    Also, check out How do I implement automatic sorting of DataGridView? which has examples of this and another library.

    0 讨论(0)
  • 2020-11-29 09:37

    I recall having issues finding something that would work when I added sorting to my datagrids too. You can implement a sortable bindable list by first adding the following class to your project. It is a list implementation that implements BindingList<T>, so that you can bind your datagrid to it, and it also supports sorting. A better explanation of the details than I could give is on MSDN here

    public class SortableBindingList<T> : BindingList<T>
    {
        private ArrayList sortedList;
        private ArrayList unsortedItems;
        private bool isSortedValue;
    
    public SortableBindingList()
    {
    }
    
    public SortableBindingList(IList<T> list)
    {
        foreach (object o in list)
        {
            this.Add((T)o);
        }
    }
    
    protected override bool SupportsSearchingCore
    {
        get
        {
            return true;
        }
    }
    
    protected override int FindCore(PropertyDescriptor prop, object key)
    {
        PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
        T item;
    
        if (key != null)
        {
           for (int i = 0; i < Count; ++i)
            {
                item = (T)Items[i];
                if (propInfo.GetValue(item, null).Equals(key))
                    return i;
            }
        }
        return -1;
    }
    
    public int Find(string property, object key)
    {
        PropertyDescriptorCollection properties =
            TypeDescriptor.GetProperties(typeof(T));
        PropertyDescriptor prop = properties.Find(property, true);
    
        if (prop == null)
            return -1;
        else
            return FindCore(prop, key);
    }
    
    protected override bool SupportsSortingCore
    {
        get { return true; }
    }
    
    
    protected override bool IsSortedCore
    {
        get { return isSortedValue; }
    }
    
    ListSortDirection sortDirectionValue;
    PropertyDescriptor sortPropertyValue;
    
    protected override void ApplySortCore(PropertyDescriptor prop,
        ListSortDirection direction)
    {
        sortedList = new ArrayList();
    
       Type interfaceType = prop.PropertyType.GetInterface("IComparable");
    
        if (interfaceType == null && prop.PropertyType.IsValueType)
        {
            Type underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);
    
             if (underlyingType != null)
            {
                interfaceType = underlyingType.GetInterface("IComparable");
            }
        }
    
        if (interfaceType != null)
        {
            sortPropertyValue = prop;
            sortDirectionValue = direction;
    
            IEnumerable<T> query = base.Items;
            if (direction == ListSortDirection.Ascending)
            {
                query = query.OrderBy(i => prop.GetValue(i));
            }
            else
            {
                query = query.OrderByDescending(i => prop.GetValue(i));
            }
            int newIndex = 0;
            foreach (object item in query)
            {
                this.Items[newIndex] = (T)item;
                newIndex++;
            }
            isSortedValue = true;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    
        }
        else
        {
            throw new NotSupportedException("Cannot sort by " + prop.Name +
                ". This" + prop.PropertyType.ToString() +
                " does not implement IComparable");
        }
    }
    
    protected override void RemoveSortCore()
    {
        int position;
        object temp;
    
        if (unsortedItems != null)
        {
            for (int i = 0; i < unsortedItems.Count; )
            {
                position = this.Find("LastName",
                    unsortedItems[i].GetType().
                    GetProperty("LastName").GetValue(unsortedItems[i], null));
                if (position > 0 && position != i)
                {
                    temp = this[i];
                    this[i] = this[position];
                    this[position] = (T)temp;
                    i++;
                }
                else if (position == i)
                    i++;
                else
                    unsortedItems.RemoveAt(i);
            }
            isSortedValue = false;
            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
    }
    
    public void RemoveSort()
    {
        RemoveSortCore();
    }
    protected override PropertyDescriptor SortPropertyCore
    {
        get { return sortPropertyValue; }
    }
    
    protected override ListSortDirection SortDirectionCore
    {
        get { return sortDirectionValue; }
    }
    
    }
    

    With that in place, the only changes you need to make to the code that you have posted above is to create a SortableBindingList based on your list and bind to the sortable list, rather than the standard one, like so:

    List<MyClass> list = new List<MyClass>();
    list.Add(new MyClass("Peter", 1202));
    list.Add(new MyClass("James", 292));
    list.Add(new MyClass("Bond", 23));
    
    // Added sortable list...
    SortableBindingList<MyClass> sortableList = new SortableBindingList<MyClass>(list);
    
    BindingSource bs = new BindingSource();
    bs.DataSource = sortableList;   // Bind to the sortable list
    

    And that will be enough to get you going.

    0 讨论(0)
提交回复
热议问题