it-swarm.com.ru

C # DataGridView сортировка с общим списком в качестве основного источника

Я использую Windows Forms DataGridView для отображения общего списка объектов MyObject.

Сначала я обертываю эту коллекцию в коллекцию BindingSource, затем:

dataGridView.DataSource = myBindingSource;

Что я хочу сделать, это позволить пользователю сортировать столбцы, щелкнув по заголовку столбца, представляющего конкретное свойство в MyObject.

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

Вопрос в том, что именно мне нужно сделать, чтобы я мог видеть стрелки сортировки в DataGridView и я мог отсортировать каждый столбец ?

17
PaN1C_Showt1Me

Мое решение таково:

Я работаю с myBindingSource самостоятельно, я делаю сортировку, группировку ... что угодно в отдельном потоке .. Затем я просто связываю результат с DataGridView .

myDataGridView.DataSource = bindingSource;

Для этого я настроил сортировку всех столбцов 'Programatically' (в конструкторе) Затем вручную добавляю стрелку (ASCENDING/DESCENDING) , Установив 

cell.SortGlyphDirection = ... ; 

в коде позади.

1
PaN1C_Showt1Me

Полный код для сортировки столбца datagridview, источником данных которого является общий список

//-----------------------------------------------------------------------------------------
//In the form - In constructor or form load, populate the grid.
//--------------------------------------------------------------------------------------------

    List<student> students;

    private void PopulateList()
    {
        student std1 = new student("sss", 15, "Female");
        student std2 = new student("ddd", 12, "Male");
        student std3 = new student("zzz", 16, "Male");
        student std4 = new student("qqq", 14, "Female");
        student std5 = new student("aaa", 11, "Male");
        student std6 = new student("lll", 13, "Female");

        students = new List<student>();
        students.Add(std1);
        students.Add(std2);
        students.Add(std3);
        students.Add(std4);
        students.Add(std5);
        students.Add(std6);

        dataGridView1.DataSource = students;
    }


//---------------------------------------------------------------------------------------------
//Comparer class to perform sorting based on column name and sort order
//---------------------------------------------------------------------------------------------


class StudentComparer : IComparer<Student>
{
    string memberName = string.Empty; // specifies the member name to be sorted
    SortOrder sortOrder = SortOrder.None; // Specifies the SortOrder.

    /// <summary>
    /// constructor to set the sort column and sort order.
    /// </summary>
    /// <param name="strMemberName"></param>
    /// <param name="sortingOrder"></param>
    public StudentComparer(string strMemberName, SortOrder sortingOrder)
    {
        memberName = strMemberName;
        sortOrder = sortingOrder;
    }

    /// <summary>
    /// Compares two Students based on member name and sort order
    /// and return the result.
    /// </summary>
    /// <param name="Student1"></param>
    /// <param name="Student2"></param>
    /// <returns></returns>
    public int Compare(Student Student1, Student Student2)
    {
        int returnValue = 1;
        switch (memberName)
        {
            case "Name" :
                if (sortOrder == SortOrder.Ascending)
                {
                    returnValue = Student1.Name.CompareTo(Student2.Name);
                }
                else
                {
                    returnValue = Student2.Name.CompareTo(Student1.Name);
                }

                break;
            case "Sex":
                if (sortOrder == SortOrder.Ascending)
                {
                    returnValue = Student1.Sex.CompareTo(Student2.Sex);
                }
                else
                {
                    returnValue = Student2.Sex.CompareTo(Student1.Sex);
                }
                break;
            default:
                if (sortOrder == SortOrder.Ascending)
                {
                    returnValue = Student1.Name.CompareTo(Student2.Name);
                }
                else
                {
                    returnValue = Student2.Name.CompareTo(Student1.StudentId);
                }
                break;
        }
        return returnValue;
    }
}



//---------------------------------------------------------------------------------------------
// Performing sort on click on Column Header
//---------------------------------------------------------------------------------------------

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        //get the current column details
        string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name;
        SortOrder strSortOrder = getSortOrder(e.ColumnIndex);

        students.Sort(new StudentComparer(strColumnName, strSortOrder));
        dataGridView1.DataSource = null;
        dataGridView1.DataSource = students;
        customizeDataGridView();
        dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder;
    }

   /// <summary>
    /// Get the current sort order of the column and return it
    /// set the new SortOrder to the columns.
    /// </summary>
    /// <param name="columnIndex"></param>
    /// <returns>SortOrder of the current column</returns>
    private SortOrder getSortOrder(int columnIndex)
    {
        if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None ||
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending)
        {
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
            return SortOrder.Ascending;
        }
        else
        {
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
            return SortOrder.Descending;
        }
    }
30
Asish

Мне трудно поверить, что сетка не обеспечивает базовую сортировку из коробки, никакого кода не требуется. В конце концов, довольно глупо обрабатывать событие щелчка в заголовке и вызывать DataGridView.Sort с указанием столбца (определяется тем, что было нажато, отслеживается сеткой) и направлением сортировки (определяется текущим состоянием сортировки, отслеживается сеткой). ). 

Почему просто не существует свойства SortMode или AllowUserToSort, которое по умолчанию делает то же самое?

Я привязал свою сетку к списку, а свойства, которым я сопоставил столбцы, - это все основные типы, такие как string, int, DateTime и так далее. Все из которых являются сопоставимыми. Так с какой стати мне нужно написать хотя бы одну строку кода? Особенно учитывая, что документация гласит:

По умолчанию пользователи могут сортировать данные в элемент управления DataGridView, нажав заголовок столбца текстового поля.

MSDN

Это документ по Framework 3.0, и я нацеливаюсь на 3.5, но все «другие версии» относятся к версиям Visual Studio, а не к версиям Framework. Что здесь происходит, Microsoft?!?

9
The Dag

Хорошее решение в этой статье «Представление списка SortableBindingList»: http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/

5
Juan Camilo Caro

Вот более простое решение для сортировки по столбцам с использованием Reflection и Linq. DataSrid DataGridView1 установлен для CompareList, который объявлен как:

    private List<CompareInfo> compareList;


    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        string strColumnName = dataGridView1.Columns[e.ColumnIndex].Name;
        SortOrder strSortOrder = getSortOrder(e.ColumnIndex);

        if (strSortOrder == SortOrder.Ascending)
        {
            compareList = compareList.OrderBy(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList();
        }
        else
        {
            compareList = compareList.OrderByDescending(x => typeof(CompareInfo).GetProperty(strColumnName).GetValue(x, null)).ToList();
        }
        dataGridView1.DataSource = compareList;
        dataGridView1.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = strSortOrder;
    }

    private SortOrder getSortOrder(int columnIndex)
    {
        if (dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.None ||
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection == SortOrder.Descending)
        {
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
            return SortOrder.Ascending;
        }
        else
        {
            dataGridView1.Columns[columnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
            return SortOrder.Descending;
        }
    }


public class CompareInfo
{
    public string FileName { get; set; }

    public string UAT_Folder { get; set; }

    public string UAT_Path
    {
        get { return UAT_Folder + FileName; }
    }

    public string PROD_Folder { get; set; }

    public string PROD_Path
    {
        get { return PROD_Folder + FileName; }
    }
}
1
Jeff Qi

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

    private string _lastSortColumn;
    private ListSortDirection _lastSortDirection;

    public void Sort(DataGridViewColumn column)
    {
        // Flip sort direction, if the column chosen was the same as last time
        if (column.Name == _lastSortColumn)
            _lastSortDirection = 1 - _lastSortDirection;
        // Otherwise, reset the sort direction to its default, ascending
        else
        {
            _lastSortColumn = column.Name;
            _lastSortDirection = ListSortDirection.Ascending;
        }

        // Prep data for sorting
        var data = (IEnumerable<dynamic>)DataSource;
        var orderProperty = column.DataPropertyName;

        // Sort data
        if (_lastSortDirection == ListSortDirection.Ascending)
            DataSource = data.OrderBy(x => x.GetType().GetProperty(orderProperty).GetValue(x, null)).ToList();
        else
            DataSource = data.OrderByDescending(x => x.GetType().GetProperty(orderProperty).GetValue(x, null)).ToList();

        // Set direction of the glyph
        Columns[column.Index].HeaderCell.SortGlyphDirection
            = _lastSortDirection == ListSortDirection.Ascending
            ? SortOrder.Ascending : SortOrder.Descending;
    }

Затем вы можете переопределить метод click header, чтобы вызвать функцию сортировки:

    protected override void OnColumnHeaderMouseClick(DataGridViewCellMouseEventArgs e)
    {
        base.OnColumnHeaderMouseClick(e);

        var column = Columns[e.ColumnIndex];

        if (column.SortMode == DataGridViewColumnSortMode.Automatic
            || column.SortMode == DataGridViewColumnSortMode.NotSortable)
            Sort(column);
    }
0
Andre Vallestero

Другой вариант решения проблемы сортировки с DataGridView при привязке к List - это, если вы не имеете дело с огромным набором данных, то, возможно, вы можете попытаться преобразовать List в DataTable, а затем связать полученный DataTable с BindingSource/DataGridView. 

Это потребует специальной реализации IComparer. В моем случае я имел дело с меньшим списком, но было больше полей для отображения. Поэтому внедрение IComparer означало написание слишком большого кода. 

Проверьте это для краткого способа преобразования Списка в DataTable: https://stackoverflow.com/a/34062898/4534493

0
Naren

увидеть это искусство 

http://msdn.Microsoft.com/en-us/library/0868ft3z.aspx

прочитав его, я увидел следующее: «Этот метод сортирует содержимое DataGridView путем сравнения значений в указанном столбце. По умолчанию операция сортировки будет использовать метод Compare для сравнения пар ячеек в столбце с использованием DataGridViewCell .. ::. Значение свойства. "

С наилучшими пожеланиями, Иордания

0
IordanTanev

Возможно, вы также захотите взглянуть на этот пост, где вы можете получить две интересные ссылки для реализации настраиваемого списка SortableBindingList:

Сортировать столбцы Datagridview, когда источник данных привязан к списку (Of T)

0
alex