Подтвердить что ты не робот

Как включить сортировку DataGridView, когда пользователь нажимает на заголовок столбца?

У меня есть datagridview в моей форме, и я заполняю его этим:

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })
                                   .OrderBy(s => s.Apellidos)
                                   .ToList();

Теперь я использую s.Apellidos как сортировку по умолчанию, но я также хотел бы разрешить пользователям сортировать при нажатии на заголовок столбца.

Этот тип будет не каким-либо образом изменять данные, это просто бонус на стороне клиента, чтобы облегчить поиск информации при сканировании экрана глазами.

Спасибо за предложения.

4b9b3361

Ответ 1

Задайте весь столбец (который можно сортировать по пользователям) Свойство SortMode для Automatic

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })
                                   .OrderBy(s => s.Apellidos)
                                   .ToList();

    foreach(DataGridViewColumn column in dataGridView1.Columns)
    {

        column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

Изменить: Поскольку ваше datagridview связано с запросом linq, оно не будет сортироваться. Поэтому, пожалуйста, перейдите по ссылке которая объясняет, как создать сортируемый список привязки и затем передать его как источник данных в datagridview.

Ответ 2

Как предложил Нирадж, используйте SortableBindingList. Я использовал это очень успешно с DataGridView.

Здесь ссылка на обновленный код, который я использовал - Представление SortableBindingList - Take Two

Просто добавьте два исходных файла в свой проект, и вы будете в бизнесе.

Источник находится в SortableBindingList.zip

Ответ 3

Ваша сетка данных должна быть привязана к сортируемому списку в первую очередь.

Создайте этот обработчик событий:

    void MakeColumnsSortable_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
    {
        //Add this as an event on DataBindingComplete
        DataGridView dataGridView = sender as DataGridView;
        if (dataGridView == null)
        {
            var ex = new InvalidOperationException("This event is for a DataGridView type senders only.");
            ex.Data.Add("Sender type", sender.GetType().Name);
            throw ex;
        }

        foreach (DataGridViewColumn column in dataGridView.Columns)
            column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

И инициализируйте событие каждого из ваших datragrids следующим образом:

        dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete;

Ответ 4

Вы можете использовать событие DataGridViewColoumnHeaderMouseClick следующим образом:

Private string order = String.Empty;
private void dgvDepartment_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (order == "d")
{
        order = "a";                
dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth })   .OrderBy(s => s.Apellidos).ToList();
    }
    else
    {
        order = "d";
        dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }.OrderByDescending(s => s.Apellidos)  .ToList()
    }
}

Ответ 5

KISS: Держите его простым, глупым

Способ A: Внесите собственный SortableBindingList класс, если хотите использовать DataBinding и сортировку.

Путь B: Используйте операцию сортировки List <string> , но не работает с DataBinding.

Ответ 6

  • Создайте класс, который содержит все необходимые вам свойства, и заполните их в конструкторе

    class Student
    {
        int _StudentId;
        public int StudentId {get;}
        string _Name;
        public string Name {get;}
        ...
    
        public Student(int studentId, string name ...)
        { _StudentId = studentId; _Name = name; ... }
    }
    
  • Создайте IComparer < Студент > класс, чтобы иметь возможность сортировать

    class StudentSorter : IComparer<Student>
    {
        public enum SField {StudentId, Name ... }
        SField _sField; SortOrder _sortOrder;
    
        public StudentSorder(SField field, SortOrder order)
        { _sField = field; _sortOrder = order;}
    
        public int Compare(Student x, Student y)
        {
            if (_SortOrder == SortOrder.Descending)
            {
                Student tmp = x;
                x = y;
                y = tmp;
            }
    
            if (x == null || y == null)
                return 0;
    
            int result = 0;
            switch (_sField)
            {
                case SField.StudentId:
                    result = x.StudentId.CompareTo(y.StudentId);
                    break;
                case SField.Name:
                    result = x.Name.CompareTo(y.Name);
                    break;
                    ...
            }
    
            return result;
        }
    }
    
  • В форме, содержащей datagrid add

    ListDictionary sortOrderLD = new ListDictionary(); //if less than 10 columns
    private SortOrder SetOrderDirection(string column)
    {
        if (sortOrderLD.Contains(column))
        {
            sortOrderLD[column] = (SortOrder)sortOrderLD[column] == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
        }
        else
        {
            sortOrderLD.Add(column, SortOrder.Ascending);
        }
    
        return (SortOrder)sortOrderLD[column];
    }
    
  • В обработчике событий datagridview_ColumnHeaderMouseClick выполните что-то вроде этого

    private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        StudentSorter sorter = null;
        string column = dGV.Columns[e.ColumnIndex].DataPropertyName; //Use column name if you set it
        if (column == "StudentId")
        {
            sorter = new StudentSorter(StudentSorter.SField.StudentId, SetOrderDirection(column));
        }
        else if (column == "Name")
        {
            sorter = new StudentSorter(StudentSorter.SField.Name, SetOrderDirection(column));
        }
    
        ...
    
        List<Student> lstFD = datagridview.DataSource as List<Student>;
        lstFD.Sort(sorter);
        datagridview.DataSource = lstFD;
        datagridview.Refresh();
    }
    

Надеюсь, что это поможет

Ответ 7

Если вы получите сообщение об ошибке, например

Необработанное исключение типа 'System.NullReferenceException' произошел в System.Windows.Forms.dll

если вы работаете с SortableBindingList, ваш код, вероятно, использует некоторые циклы над строками DataGridView, а также пытается получить доступ к пустой последней строке! (BindingSource = null)

Если вам не нужно позволять пользователю добавлять новые строки непосредственно в DataGridView, эта строка кода легко решает проблему:

InitializeComponent();
m_dataGridView.AllowUserToAddRows = false; // after components initialized
...

Ответ 8

Еще один способ сделать это - использовать библиотеку "System.Linq.Dynamic". Вы можете получить эту библиотеку от Nuget. Нет необходимости в каких-либо пользовательских реализациях:).

using System.Linq.Dynamic;
private bool sortAscending = false;

private void dataGridView_ColumnHeaderMouseClick ( object sender, DataGridViewCellMouseEventArgs e )
{
    if ( sortAscending )
        dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).ToList ( );
    else
        dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).Reverse ( ).ToList ( );
    sortAscending = !sortAscending;
}

Ответ 9

На всякий случай кто-то все еще ищет его, я сделал это на VS 2008 С#.

В столбце EventHeaderMouseClick добавьте привязку данных для gridview и отправьте заказ по полю как параметр. Вы можете получить поле с щелчком:

dgView.Columns[e.ColumnIndex].Name

В моем случае имена заголовков похожи на имена полей вида.

Ответ 10

У меня есть привязка объекта BindingList < > в качестве источника данных для dataGridView.

BindingList x1;
x1 = new BindingList<sourceObject>();
BindingSource bsx1 = new BindingSource();
bsx1.DataSource = x1;
dataGridView1.DataSource = bsx1;

Когда я щелкнул заголовок столбца, сортировка не происходит. Я использовал ответ SortableBindingList, предоставленный Томом Бушеллом. Включив в свой проект два исходных файла

  • SortableBindingList.cs
  • PropertyComparer.cs

Затем это изменение внесено в мой код:

Be.Timvw.Framework.ComponentModel.SortableBindingList x1;                       // 1
x1 = new Be.Timvw.Framework.ComponentModel.SortableBindingList<sourceObject>(); // 2
BindingSource bsx1 = new BindingSource();
bsx1.DataSource = x1;
dataGridView1.DataSource = bsx1;

После этих изменений я выполнил сборку своей программы. Теперь я могу сортировать, щелкая заголовки столбцов. Только две строки нуждаются в изменении, они выделяются в фрагменте кода выше, оставляя комментарии.

Ответ 11


существует довольно простое решение при использовании Entity Framework (версия 6 в этом случае). Я не уверен, но кажется, что метод ObservableCollectionExtensions.ToBindingList<T> возвращает реализацию списка привязки сортировки. Я не нашел исходный код для подтверждения этого предположения, но объект, возвращающийся из этого метода, работает с DataGridView очень хорошо, особенно при сортировке столбцов, нажимая на его заголовки.

Код очень просто и полагается только на классы .net и entity framework:

using System.Data.Entity;

IEnumerable<Item> items = MethodCreatingItems();

var observableItems = new System.Collections.ObjectModel.ObservableCollection<Item>(items);
System.ComponentModel.BindingList<Item> source = observableItems.ToBindingList();

MyDataGridView.DataSource = source;

Ответ 12

Я предлагаю использовать DataTable.DefaultView в качестве источника данных. Тогда строка ниже.

foreach (DataGridViewColumn column in gridview.Columns)
    {
       column.SortMode = DataGridViewColumnSortMode.Automatic;
    }

После этого gridview сам будет управлять сортировкой (поддерживается восходящий или нисходящий).

Ответ 13

Вам не нужно создавать привязывающий источник данных. Если вы хотите применить сортировку для всех своих столбцов, то это более общее решение,

private int _previousIndex;
private bool _sortDirection;

private void gridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    if (e.ColumnIndex == _previousIndex)
        _sortDirection ^= true; // toggle direction

    gridView.DataSource = SortData(
        (List<MainGridViewModel>)gridReview.DataSource, gridReview.Columns[e.ColumnIndex].Name, _sortDirection);

    _previousIndex = e.ColumnIndex;
}

public List<MainGridViewModel> SortData(List<MainGridViewModel> list, string column, bool ascending)
{
    return ascending ? 
        list.OrderBy(_ => _.GetType().GetProperty(column).GetValue(_)).ToList() :
        list.OrderByDescending(_ => _.GetType().GetProperty(column).GetValue(_)).ToList();
}

Убедитесь, что вы подписали свою сетку данных на событие ColumnHeaderMouseClick. Когда пользователь нажимает на столбец, он сортируется по убыванию. Если снова нажать один и тот же заголовок столбца, сортировка будет применяться по возрастанию.