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

<p>я использую<strong> windows forms datagridview </strong>для отображения общего списка объектов <code>myobject</code>.</p><p>сначала я обертываю эту коллекцию в коллекцию <code>bindingsource</code>, затем:</p><pre><code>datagridview.datasource = mybindingsource; </code></pre><p>что я хочу сделать, это позволить пользователю сортировать столбцы, щелкнув по заголовку столбца, представляющего конкретное свойство в myobject.</p><p>я прочитал несколько статей, которые я должен сделать сортировку перед привязкой. но мне не поможет, если я хочу отсортировать столбцы в режиме реального времени, когда они уже связаны.</p><p>вопрос в том, что именно мне нужно сделать, чтобы<strong> я мог видеть стрелки сортировки </strong>в datagridview и<strong> я мог отсортировать каждый столбец </strong>?</p>

<p>мое решение таково:</p><p>я работаю с mybindingsource самостоятельно, я делаю сортировку, группировку ... что угодно в отдельном потоке .. затем я просто<strong> связываю результат с datagridview </strong>.</p><pre><code>mydatagridview.datasource = bindingsource; </code></pre><p>для этого я настроил сортировку всех столбцов <code>'programatically'</code> (в конструкторе) затем вручную добавляю стрелку (ascending/descending) , установив </p><pre><code>cell.sortglyphdirection = ... ; </code></pre><p>в коде позади.</p>

<p>полный код для сортировки столбца datagridview, источником данных которого является общий список</p><pre><code>//----------------------------------------------------------------------------------------- //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; } } </code></pre>

<p>мне трудно поверить, что сетка не обеспечивает базовую сортировку из коробки, никакого кода не требуется. в конце концов, довольно глупо обрабатывать событие щелчка в заголовке и вызывать datagridview.sort с указанием столбца (определяется тем, что было нажато, отслеживается сеткой) и направлением сортировки (определяется текущим состоянием сортировки, отслеживается сеткой). ). </p><p>почему просто не существует свойства sortmode или allowusertosort, которое по умолчанию делает то же самое?</p><p>я привязал свою сетку к списку, а свойства, которым я сопоставил столбцы, - это все основные типы, такие как string, int, datetime и так далее. все из которых являются сопоставимыми. так с какой стати мне нужно написать хотя бы одну строку кода? особенно учитывая, что документация гласит:</p><blockquote> <p>по умолчанию пользователи могут сортировать данные в элемент управления datagridview, нажав заголовок столбца текстового поля.</p> </blockquote><p> <a href="http://msdn.microsoft.com/en-us/library/ms171607%28v=vs.85%29.aspx">msdn</a> </p><p>это документ по framework 3.0, и я нацеливаюсь на 3.5, но все «другие версии» относятся к версиям visual studio, а не к версиям framework. что здесь происходит, microsoft?!?</p>

<p>хорошее решение в этой статье «представление списка sortablebindinglist»: <a href="http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/">http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/</a> </p>

<p>вот более простое решение для сортировки по столбцам с использованием reflection и linq. datasrid datagridview1 установлен для comparelist, который объявлен как:</p><pre><code> 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; } } } </code></pre>

<p>если создание собственного пользовательского элемента управления является предпочтительным, вы можете создать собственный метод сортировки, используя следующий код:</p><pre><code> 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; } </code></pre><p>затем вы можете переопределить метод click header, чтобы вызвать функцию сортировки:</p><pre><code> 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); } </code></pre>

<p>другой вариант решения проблемы сортировки с datagridview при привязке к list - это, если вы не имеете дело с огромным набором данных, то, возможно, вы можете попытаться преобразовать list в datatable, а затем связать полученный datatable с bindingsource/datagridview. </p><p>это потребует специальной реализации icomparer. в моем случае я имел дело с меньшим списком, но было больше полей для отображения. поэтому внедрение icomparer означало написание слишком большого кода. </p><p>проверьте это для краткого способа преобразования списка в datatable: <a href="https://stackoverflow.com/a/34062898/4534493">https://stackoverflow.com/a/34062898/4534493</a> </p>

<p>увидеть это искусство </p><p> <a href="http://msdn.microsoft.com/en-us/library/0868ft3z.aspx">http://msdn.microsoft.com/en-us/library/0868ft3z.aspx</a> </p><p>прочитав его, я увидел следующее: «этот метод сортирует содержимое datagridview путем сравнения значений в указанном столбце. по умолчанию операция сортировки будет использовать метод compare для сравнения пар ячеек в столбце с использованием datagridviewcell .. ::. значение свойства. "</p><p>с наилучшими пожеланиями, иордания</p>

<p>возможно, вы также захотите взглянуть на этот пост, где вы можете получить две интересные ссылки для реализации настраиваемого списка sortablebindinglist:</p><p> <a href="https://stackoverflow.com/questions/4899908/sort-datagridview-columns-when-datasource-binded-to-listof-t/4907081#4907081">сортировать столбцы datagridview, когда источник данных привязан к списку (of t)</a> </p>