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

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

问题描述

我正在构建一个Windows窗体应用程序,显示一个自定义类 Record 对象,并将它们排序在我的 SortableBindingList< ;记录> record_list 。当我开始我的程序,我有一些虚拟记录加载到这个列表中已经为了测试。



SortableBindingList< T> 已从



添加数据后的结果:





最后,点击UserName头后,结果:





所以,每次更新DataSource时,是否必须强制排序?如果是这样的话,我该怎么称呼这种方式?



谢谢你提前协助!

解决方案

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



SortableBindingList< T> 需要一些更改,以便在列表中进行某些更改时保持列表的排序。这是我做的更改的完整代码。



注意 OnListChanged 方法 BindingList 将会在添加和删除项目后自动调用。但是如果您需要 OnListChanged 也会在更改项目属性后运行,则应为您的模型类实施 INotifyPropertyChanged / p>

  using System; 
使用System.Collections.Generic;
使用System.ComponentModel;
使用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底层类型= Nullable.GetUnderlyingType(prop.PropertyType);
if(underlyingType!= null)
{
interfaceType =底部类型.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(查询中的对象项)
{
this.Items [newIndex] =(T)项;
newIndex ++;
}
isSortedValue = true;
sorted = true;
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset,-1));
sorted = false;
}
else
{
抛出新的NotSupportedException(不能排序+ prop.Name +
这个+ prop.PropertyType.ToString()+
不实现IComparable);
}
}
bool sorted = 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(!sort&& sortPropertyValue!= null)
ApplySortCore(sortPropertyValue,sortDirectionValue);
else
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&lt; T&gt; - DataGridView不会自动对更改进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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