且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 SortableBindingList;- DataGridView 不会自动对更改进行排序

更新时间:2023-02-20 15:55:43

当列表更改时,您需要应用排序.

SortableBindingList 需要一些更改以保持列表在某些列表中所做的更改.这是我所做更改的完整代码.

注意BindingListOnListChanged方法会在添加删除项后自动调用.但是如果你需要 OnListChanged 在改变项目的属性后也运行,你应该为你的模型类实现 INotifyPropertyChanged.

使用系统;使用 System.Collections.Generic;使用 System.ComponentModel;使用 System.Linq;公共类 SortableBindingList: BindingList{private bool isSortedValue;ListSortDirection sortDirectionValue;PropertyDescriptor sortPropertyValue;公共 SortableBindingList() : base() { }公共 SortableBindingList(IList<T> list) : base(list) { }protected override void ApplySortCore(PropertyDescriptor prop,ListSortDirection 方向){Type interfaceType = prop.PropertyType.GetInterface("IComparable");if (interfaceType == null && prop.PropertyType.IsValueType){类型underlyingType = Nullable.GetUnderlyingType(prop.PropertyType);如果(底层类型!= null){interfaceType = 底层类型.GetInterface("IComparable");}}如果(接口类型!= null){sortPropertyValue = 道具;sortDirectionValue = 方向;IEnumerable查询 = base.Items;if (direction == ListSortDirection.Ascending)查询 = query.OrderBy(i => prop.GetValue(i));别的查询 = query.OrderByDescending(i => prop.GetValue(i));int newIndex = 0;foreach(查询中的对象项){this.Items[newIndex] = (T)item;新索引++;}isSortedValue = true;排序=真;this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));排序=假;}别的{throw new NotSupportedException("无法排序" + prop.Name +".this" + prop.PropertyType.ToString() +" 没有实现 IComparable");}}布尔排序=假;受保护的覆盖 PropertyDescriptor SortPropertyCore{得到 { 返回 sortPropertyValue;}}受保护的覆盖 ListSortDirection SortDirectionCore{得到 { 返回 sortDirectionValue;}}protected override bool SupportsSortingCore{得到 { 返回真;}}protected override bool IsSortedCore{得到 { 返回 isSortedValue;}}protected override void RemoveSortCore(){isSortedValue = false;sortPropertyValue = null;}protected override void OnListChanged(ListChangedEventArgs e){if (!sorting && sortPropertyValue != null)ApplySortCore(sortPropertyValue, sortDirectionValue);别的base.OnListChanged(e);}}

I'm building a Windows Forms Application that displays a custom class Record objects and sorts them by how long they've been in my SortableBindingList<Record> record_list. When I start my program, I have some "dummy" records loaded into this list already for the sake of testing.

The SortableBindingList<T> has been taken from here.

public partial class Form1 : Form
{
    public SortableBindingList<Record> record_list = new SortableBindingList<Record> { };
    public static DataGridViewCellStyle style = new DataGridViewCellStyle();
    public Form1()
    {
        InitializeComponent();
        dataGridView.DataSource = record_list;
        FillData(); //Temporary function to insert dummy data for demo.
        dataGridView.CellFormatting += new System.Windows.Forms.DataGridViewCellFormattingEventHandler(this.cell_formatting);
        this.Controls.Add(dataGridView);
        this.dataGridView.RowHeadersVisible = false;
        this.dataGridView.Sort(this.dataGridView.Columns["UserName"], ListSortDirection.Ascending);

        start_timer();                 
    }

Result before "new" data is added (note: this was alphabetized automatically, specifically entered into the list out of alphabetical order):

Result after data is added:

Finally, result after I click the "UserName" header:

So, must I force a sort every time my DataSource is updated? If that's the case, how do I call a sort in such a manner?

Thank you for your assistance in advance!

You need to apply sort when the list changes.

The SortableBindingList<T> needs some changes to keep the the list sorted when some changes made in list. Here is the full code with changes which I made.

Pay attention The OnListChanged method of BindingList will be called automatically after adding and removing items. But if you need to OnListChanged also runs after changing properties of items, you should implement INotifyPropertyChanged for your model class.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public class SortableBindingList<T> : BindingList<T>
{
    private bool isSortedValue;
    ListSortDirection sortDirectionValue;
    PropertyDescriptor sortPropertyValue;
    public SortableBindingList() : base() { }
    public SortableBindingList(IList<T> list) : base(list) { }
    protected override void ApplySortCore(PropertyDescriptor prop,
        ListSortDirection direction)
    {
        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;
            sorting = true;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
            sorting = false;
        }
        else
        {
            throw new NotSupportedException("Cannot sort by " + prop.Name +
                ". This" + prop.PropertyType.ToString() +
                " does not implement IComparable");
        }
    }
    bool sorting = false;
    protected override PropertyDescriptor SortPropertyCore
    {
        get { return sortPropertyValue; }
    }
    protected override ListSortDirection SortDirectionCore
    {
        get { return sortDirectionValue; }
    }
    protected override bool SupportsSortingCore
    {
        get { return true; }
    }
    protected override bool IsSortedCore
    {
        get { return isSortedValue; }
    }
    protected override void RemoveSortCore()
    {
        isSortedValue = false;
        sortPropertyValue = null;
    }
    protected override void OnListChanged(ListChangedEventArgs e)
    {
        if (!sorting && sortPropertyValue != null)
            ApplySortCore(sortPropertyValue, sortDirectionValue);
        else
            base.OnListChanged(e);
    }
}