Сделать все столбцы datagridview отсортированными

У меня есть форма Windows с datagridview.

Идеальная ситуация:

Пользователь нажимает на любой из девяти столбцов, и программа сортирует все данные, если столбец с щелчком содержит числа, мне нужно, чтобы наименьшее число было сверху. Если столбец с кликом содержит строку, которую я хотел бы сортировать по алфавиту (A-Z).

То, что у меня есть прямо сейчас:

Я видел старый вопрос о переполнении стека, где OP, как сортировать datagridview при нажатии заголовка "a". Разница с моей заключается в том, что я хочу, чтобы мое datagridview было отсортировано по любому из девяти столбцов.

У меня есть этот код, украденный из вопроса, который я нашел:

dataGridView2.DataSource = listPlayers.Select(s => new { voornaam = s.Voornaam, 
                                                        Achternaam = s.Achternaam, 
                                                        positie = s.Positie, 
                                                        Nationaltieit = s.Nationaliteit, 
                                                        Leeftijd = s.Age, 
                                                        Aanval = s.Aanval, 
                                                        Verdediging = s.Verdediging, 
                                                        Gemiddeld = s.Gemiddeld, 
                                                        waarde = s.TransferWaarde })
                                   .OrderBy(s => s.Achternaam)
                                   .ToList();

foreach(DataGridViewColumn column in dataGridView2.Columns)
    {
        dataGridView2.Columns[column.Name].SortMode =
                                  DataGridViewColumnSortMode.Automatic;
    }

Это позволяет только пользователю заказать "Achternaam", когда он нажимает на один из девяти столбцов. Я хочу, когда пользователь нажимает на столбец Nationaliteit, данные сортируются с помощью An сверху. И так далее для каждого столбца

Это список listplayers:

namespace SimulatorSimulator
{
    class SpelerData
    {
        public string Voornaam { get; set; }
        public string Achternaam { get; set; }
        public string Positie { get; set; }
        public string Nationaliteit { get; set; }
        public int Age { get; set; }
        public int Aanval { get; set; }
        public int Verdediging { get; set; }
        public int Gemiddeld { get; set; }
        public string TransferWaarde { get; set; }
    }
}

И в основном классе:

 List<SpelerData> listPlayers = new List<SpelerData>();

Некоторые фиктивные данные:

Romelu;Lukaku;Aanvaller;Belgie;22;87;12;50;41.000.000,00    
Raheem ;Sterling;Aanvaller;Engeland;21;84;30;57;35.000.000,00    
Zlatan ;Ibrahimovic;Aanvaller;Zweden;34;87;21;54;34.500.000,00

Ответ 1

Я думаю, что самый простой способ для вашего дела - разместить ваши данные в таблице Database. Таким образом, вы можете просто использовать это как data source для своего dataGridView2, и вы сможете легко выполнить сортировку, щелкнув столбец заголовка.

Альтернативным способом будет использование SortableBindingList (статья) в качестве другой ответ также предложил.

Но если оба варианта не относятся к вашим выборам, следующий простой способ, о котором я мог думать, - создать событие из ColumnHeaderMouseClick, а затем вы можете перечислить свою сортировку соответствующим образом, используя e.ColumnIndex и правое "отображение" (Словарь) на ваш подготовленный IEnumerable<SpelerData>

Итак, в вашей форме загружайте, вы делаете что-то вроде этого:

Dictionary<int, IEnumerable<SpelerData>> queryDict = new Dictionary<int, IEnumerable<SpelerData>>(); //Prepare a dictionary of query
private void form_load(object sender, EventArgs e) {
    dataGridView2.DataSource = listPlayers.OrderBy(x => x.Achternaam).ToList();
    queryDict.Add(0, listPlayers.OrderBy(x => x.Voornaam));
    queryDict.Add(1, listPlayers.OrderBy(x => x.Achternaam));
    queryDict.Add(2, listPlayers.OrderBy(x => x.Positie));
    queryDict.Add(3, listPlayers.OrderBy(x => x.Nationaliteit));
    queryDict.Add(4, listPlayers.OrderBy(x => x.Age));
    queryDict.Add(5, listPlayers.OrderBy(x => x.Aanval));
    queryDict.Add(6, listPlayers.OrderBy(x => x.Verdediging));
    queryDict.Add(7, listPlayers.OrderBy(x => x.Gemiddeld));
    queryDict.Add(8, listPlayers.OrderBy(x => x.TransferWaarde));
}

И затем в событии ColumnHeaderMouseClick просто выполните:

private void dataGridView2_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
    dataGridView2.DataSource = queryDict[e.ColumnIndex].ToList();
}

И вы получите нужное поведение.

Обратите внимание, что поскольку IEnumerable выполняется с задержкой, ранняя подготовка Dictionary вообще не повлияет на производительность. Единственное, что вам нужно добавить, это 9 строк кода в form_Load для подготовки словаря и 1 строки кода в вашем событии dataGridView2_ColumnHeaderMouseClick. Это самое простое решение, кроме двух ранее упомянутых, о которых я мог думать.

Ответ 2

Вы можете использовать SortableBindingList

SortableBindingList<T> list = new SortableBindingList<T>();

//Add items to list

dataGridView.DataSource = list ;

Это позволит сортировать при нажатии на заголовок столбца

public class SortableBindingList<T> : BindingList<T>
{
    private readonly Dictionary<Type, PropertyComparer<T>> comparers;
    private bool isSorted;
    private ListSortDirection listSortDirection;
    private PropertyDescriptor propertyDescriptor;

    public SortableBindingList()
        : base(new List<T>())
    {
        this.comparers = new Dictionary<Type, PropertyComparer<T>>();
    }

    public SortableBindingList(IEnumerable<T> enumeration)
        : base(new List<T>(enumeration))
    {
        this.comparers = new Dictionary<Type, PropertyComparer<T>>();
    }

    protected override bool SupportsSortingCore
    {
        get { return true; }
    }

    protected override bool IsSortedCore
    {
        get { return this.isSorted; }
    }

    protected override PropertyDescriptor SortPropertyCore
    {
        get { return this.propertyDescriptor; }
    }

    protected override ListSortDirection SortDirectionCore
    {
        get { return this.listSortDirection; }
    }

    protected override bool SupportsSearchingCore
    {
        get { return true; }
    }

    protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
    {
        List<T> itemsList = (List<T>)this.Items;

        Type propertyType = property.PropertyType;
        PropertyComparer<T> comparer;
        if (!this.comparers.TryGetValue(propertyType, out comparer))
        {
            comparer = new PropertyComparer<T>(property, direction);
            this.comparers.Add(propertyType, comparer);
        }

        comparer.SetPropertyAndDirection(property, direction);
        itemsList.Sort(comparer);

        this.propertyDescriptor = property;
        this.listSortDirection = direction;
        this.isSorted = true;

        this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    protected override void RemoveSortCore()
    {
        this.isSorted = false;
        this.propertyDescriptor = base.SortPropertyCore;
        this.listSortDirection = base.SortDirectionCore;

        this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
    }

    protected override int FindCore(PropertyDescriptor property, object key)
    {
        int count = this.Count;
        for (int i = 0; i < count; ++i)
        {
            T element = this[i];
            if (property.GetValue(element).Equals(key))
            {
                return i;
            }
        }

        return -1;
    }
}

Ответ 3

Если вы хотите использовать отражение, вы можете сделать что-то вроде следующего.

ПРИМЕЧАНИЕ. Я предполагаю, что вы используете DataGridView.ColumnHeaderMouseClick Event, но это не изменяется ядро этого подхода. Дело в том, что вам нужно динамически идентифицировать строковое значение, представляющее имя столбца, который вы хотите OrderBy. Вы можете жестко закодировать эту связь, если вам действительно нужно/нужно.

private void dataGridView2_ColumnHeaderMouseClick(
    object sender, DataGridViewCellMouseEventArgs e)
{
    ...
    var sortCol = dataGridView2.Columns[e.ColumnIndex];
    var colName = sortCol.Name;

    dataGridView2.DataSource = listPlayers.Select(s => new { voornaam = s.Voornaam, Achternaam = s.Achternaam, positie = s.Positie, Nationaltieit = s.Nationaliteit, Leeftijd = s.Age, Aanval = s.Aanval, Verdediging = s.Verdediging, Gemiddeld = s.Gemiddeld, waarde = s.TransferWaarde })
                                          .OrderBy(s => typeof(SpelerData).GetProperty(colName))
                                          .ToList();
    ...
}