使用 SortableBindingList<T>;- DataGridView 不会自动对更改进行排序 [英] Using SortableBindingList&lt;T&gt; - DataGridView doesn&#39;t automatically sort on changes

查看:14
本文介绍了使用 SortableBindingList<T>;- DataGridView 不会自动对更改进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个 Windows 窗体应用程序,它显示一个自定义类 Record 对象,并按照它们在我的 SortableBindingList 中的时间对它们进行排序>记录列表.当我启动我的程序时,为了测试,我已经将一些虚拟"记录加载到这个列表中.

SortableBindingList 取自

添加数据后的结果:

最后,点击用户名"标题后的结果:

那么,每次更新我的数据源时我都必须强制排序吗?如果是这样,我如何以这种方式调用排序?

提前感谢您的帮助!

解决方案

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

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

这篇关于使用 SortableBindingList<T>;- DataGridView 不会自动对更改进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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