#c# #winforms #data-binding #sorting #datagridview
#c# #winforms #привязка данных #сортировка #datagridview
Вопрос:
У меня есть форма с datagridview на ней. DataGridView привязан к BindingSource:
public class Address
{
public string State { get; set; }
public string City { get; set; }
public string Street { get; set; }
}
this.addressBindingSource.DataSource = typeof(Address);
this.dataGridView1.DataSource = this.addressBindingSource;
Я заполняю DataSource
вот так:
addressBindingSource.DataSource = new BindingList<Address>
{
new Address {State = "S1", City = "C1", Street = "S1"},
new Address {State = "S1", City = "C1", Street = "S2"},
new Address {State = "S1", City = "C1", Street = "S3"},
new Address {State = "S1", City = "C2", Street = "S4"},
new Address {State = "S1", City = "C2", Street = "S5"},
new Address {State = "S1", City = "C2", Street = "S6"},
};
Я пытаюсь включить сортировку для этого datagridview. Я установил SortMode
значение Programmatic
для всех столбцов dataGridView1. И я добавил обработчик событий для ColumnHeaderMouseClick
:
private Dictionary<int, string> columnIndexPropertyNameDictionary = new Dictionary<int, string>
{
{0, "State"},
{1, "City"},
{2, "Street"},
};
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
if (e.ColumnIndex < 0)
return;
for (int i = 0; i < dataGridView1.Columns.Count; i )
{
if (i == e.ColumnIndex)
continue;
dataGridView1.Columns[i].HeaderCell.SortGlyphDirection = SortOrder.None;
}
var column = dataGridView1.Columns[e.ColumnIndex];
if (column.SortMode != DataGridViewColumnSortMode.Programmatic)
return;
var sortGlyphDirection = column.HeaderCell.SortGlyphDirection;
switch (sortGlyphDirection)
{
case SortOrder.None:
case SortOrder.Ascending:
addressBindingSource.Sort = columnIndexPropertyNameDictionary[e.ColumnIndex] " ASC";
column.HeaderCell.SortGlyphDirection = SortOrder.Descending;
break;
case SortOrder.Descending:
addressBindingSource.Sort = columnIndexPropertyNameDictionary[e.ColumnIndex] " DESC";
column.HeaderCell.SortGlyphDirection = SortOrder.Ascending;
break;
}
}
Сортировка по-прежнему не работает. Что я делаю не так?
Комментарии:
1. Я заметил это
addressBindingSource.SupportsSorting = false
. Почему это?
Ответ №1:
Проблема в том, что готовый список привязок не поддерживает сортировку! Я знаю — звучит глупо, но так оно и есть.
Вам нужно реализовать свой собственный SortableBindingList. Пример кода для этого приведен ниже.
Этот код взят отсюда, и у меня нет времени его тщательно проверять. Если это не работает, тогда найдите в Google термин SortableBindingList, существует множество реализаций.
public class SortableBindingList<t> : BindingList<t>
{
private bool m_Sorted = false;
private ListSortDirection m_SortDirection = ListSortDirection.Ascending;
private PropertyDescriptor m_SortProperty = null;
protected override bool SupportsSortingCore
{
get
{
return true;
}
}
protected override bool IsSortedCore
{
get
{
return m_Sorted;
}
}
protected override ListSortDirection SortDirectionCore
{
get
{
return m_SortDirection;
}
}
protected override PropertyDescriptor SortPropertyCore
{
get
{
return m_SortProperty;
}
}
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
m_SortDirection = direction;
m_SortProperty = prop;
var listRef = this.Items as List<t>;
if (listRef == null)
return;
var comparer = new SortComparer<t>(prop, direction);
listRef.Sort(comparer);
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
}
Комментарии:
1. 1 для SortableBindingList. Наконец, я иду в направлении сортировки.
Ответ №2:
Я использую эту простую функцию при добавлении новой строки:
dataGridViewResult.Sort(dataGridViewResult.Columns[0], ListSortDirection.Descending);
Ответ №3:
private void sortButton_Click(object sender, System.EventArgs e)
{
// Check which column is selected, otherwise set NewColumn to null.
DataGridViewColumn newColumn =
dataGridView1.Columns.GetColumnCount(
DataGridViewElementStates.Selected) == 1 ?
dataGridView1.SelectedColumns[0] : null;
DataGridViewColumn oldColumn = dataGridView1.SortedColumn;
ListSortDirection direction;
// If oldColumn is null, then the DataGridView is not currently sorted.
if (oldColumn != null)
{
// Sort the same column again, reversing the SortOrder.
if (oldColumn == newColumn amp;amp;
dataGridView1.SortOrder == SortOrder.Ascending)
{
direction = ListSortDirection.Descending;
}
else
{
// Sort a new column and remove the old SortGlyph.
direction = ListSortDirection.Ascending;
oldColumn.HeaderCell.SortGlyphDirection = SortOrder.None;
}
}
else
{
direction = ListSortDirection.Ascending;
}
// If no column has been selected, display an error dialog box.
if (newColumn == null)
{
MessageBox.Show("Select a single column and try again.",
"Error: Invalid Selection", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
dataGridView1.Sort(newColumn, direction);
newColumn.HeaderCell.SortGlyphDirection =
direction == ListSortDirection.Ascending ?
SortOrder.Ascending : SortOrder.Descending;
}
}
Ответ №4:
Есть более простой способ. Вы должны установить тип данных столбца следующим образом:
private void DataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.Index == 0)
{
e.Column.ValueType = typeof(int);
e.Column.CellTemplate.ValueType = typeof(int);
}
}
или, если у вас есть имя объекта столбца:
ColumnName.ValueType = typeof(int);