С# DataGridView сортировка с общим списком в качестве основного источника
Я использую Windows Forms DataGridView, чтобы отобразить общий список объектов MyObject
.
Прежде всего, я переношу эту коллекцию в коллекцию BindingSource
, а затем:
dataGridView.DataSource = myBindingSource;
Что я хочу сделать, так это разрешить пользователю сортировать столбцы, щелкнув по заголовку столбца, представляющего конкретное свойство в MyObject.
Я прочитал несколько статей, которые мне нужно будет сортировать перед привязкой. Но это не помогает мне, если я хочу сортировать столбцы в реальном времени, будучи сказанным, когда он уже привязан.
Вопрос в том, что именно мне нужно сделать, поэтому я мог видеть стрелки сортировки в DataGridView и , я мог сортировать каждый столбец?
Ответы
Ответ 1
Мое решение таково:
Я работаю с myBindingSource самостоятельно, я сортирую, группирую... что бы ни было в отдельном потоке.
Затем я просто привязываю результат к DataGridView.
myDataGridView.DataSource = bindingSource;
С этой целью я установил все столбцы, которые будут отсортированы 'Programatically'
(в дизайнере)
Затем я вручную добавляю стрелку (ASCENDING/DESCENDING)
установив
cell.SortGlyphDirection = ... ;
в коде.
Ответ 2
Полный код для сортировки столбца 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;
}
}
Ответ 3
Мне трудно поверить, что сетка не обеспечивает базовую сортировку из коробки, а не код. В конце концов, довольно глупо обрабатывать событие щелчка заголовка и вызывать DataGridView.Sort, указывающий столбец (определяется тем, что было нажато, отслеживается сеткой) и направлением сортировки (определяется текущим состоянием сортировки, отслеживается сеткой).
Почему нет просто свойства SortMode или AllowUserToSort, которое по умолчанию делает то же самое?
Я привязал свою сетку к списку, а свойства, с которыми я сопоставил столбцы, - это все базовые типы, такие как string, int, DateTime и т.д. Все из них являются IComparable. Так почему же мне нужно писать даже одну строку кода? Особенно учитывая, что документация гласит:
По умолчанию пользователи могут сортировать данные в элемент управления DataGridView, нажав заголовок столбца текстового поля.
MSDN
Это документ 3.0 Framework, и я нацелен на 3,5, но "другие версии" относятся ко всем версиям Visual Studio, а не к версиям Framework. Что происходит здесь, Microsoft?!?
Ответ 4
Хорошее решение в этой статье "Представление SortableBindingList":
http://www.timvw.be/2007/02/22/presenting-the-sortablebindinglistt/
Ответ 5
см. эту статью
http://msdn.microsoft.com/en-us/library/0868ft3z.aspx
прочитав его, я увидел это: "Этот метод сортирует содержимое DataGridView, сравнивая значения в указанном столбце. По умолчанию операция сортировки будет использовать метод Compare для сравнения пар ячеек в столбце с помощью DataGridViewCell..::. Значение свойства.
С наилучшими пожеланиями,
Iordan
Ответ 6
Вы также можете взглянуть на этот пост, где вы можете получить две интересные ссылки для реализации настраиваемого SortableBindingList:
Сортировка столбцов Datagridview при привязке источника данных к списку (Of T)
Ответ 7
Вот более простое решение для сортировки по столбцу с использованием Reflection и Linq. dataGridView1 DataSource установлен в 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; }
}
}
Ответ 8
Другой вариант решения проблемы сортировки с DataGridView при привязке к List - если вы не имеете дело с огромным набором данных, то, вероятно, вы можете попытаться преобразовать List в DataTable, а затем привязать полученный DataTable к BindingSource/DataGridView,
Это потребовало бы специальной реализации IComparer. В моем случае я имел дело с меньшим списком, но было больше полей для отображения. Таким образом, реализация IComparer означала запись слишком большого количества кодовых табличек.
Проверьте это для краткого способа преобразования List в DataTable: fooobar.com/info/34403/...