Использование SortableBindingList‹T› — DataGridView не выполняет автоматическую сортировку изменений

Я создаю приложение Windows Forms, которое отображает объекты пользовательского класса Record и сортирует их по тому, как долго они находились в моем SortableBindingList<Record> record_list. Когда я запускаю свою программу, у меня в этот список загружаются некоторые "фиктивные" записи уже ради тестирования.

SortableBindingList<T> был взят из здесь.

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

Результат перед добавлением «новых» данных (примечание: они были автоматически отсортированы по алфавиту, специально введены в список не в алфавитном порядке):

введите здесь описание изображения

Результат после добавления данных:

введите здесь описание изображения

Наконец, результат после того, как я нажму заголовок «UserName»:

введите здесь описание изображения

Итак, должен ли я принудительно выполнять сортировку каждый раз, когда мой источник данных обновляется? Если это так, как мне вызвать сортировку таким образом?

Спасибо за вашу помощь заранее!


person MrDysprosium    schedule 16.09.2016    source источник
comment
Стандартного класса SortableBindingList<T> не существует, о каком из них вы говорите?   -  person Ivan Stoev    schedule 16.09.2016
comment
Это пользовательский класс, взятый из: stackoverflow.com/questions/23661195/   -  person MrDysprosium    schedule 16.09.2016
comment
Вот почему это не работает - это довольно простая реализация, типичная для ответа SO.   -  person Ivan Stoev    schedule 16.09.2016


Ответы (1)


Вам нужно применить сортировку при изменении списка.

В SortableBindingList<T> требуются некоторые изменения, чтобы сохранить сортировку списка при внесении некоторых изменений в список. Вот полный код с изменениями, которые я сделал.

Обратите внимание: метод OnListChanged для BindingList будет вызываться автоматически после добавления и удаления элементов. Но если вам нужно, чтобы OnListChanged также запускалось после изменения свойств элементов, вы должны реализовать INotifyPropertyChanged для своего класса модели.

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);
    }
}
person Reza Aghaei    schedule 16.09.2016