WinForms: DataGridView - programmatic sorting
I've got a form with datagridview on it. dataGridView is binded to 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;
I fill DataSource
like this:
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", Stree开发者_Python百科t = "S5"},
new Address {State = "S1", City = "C2", Street = "S6"},
};
I'm trying to enable sorting for this datagridview. I set SortMode
to Programmatic
for all the columns of dataGridView1. And I added an event handler for 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;
}
}
Sorting still doesn't work. What am I doing wrong?
The problem is that out of the box the BindingList does not support sorting! I know - sounds dumb but that is how it is.
You need to implement your own SortableBindingList. An example of the code for that is below.
This code came from here and I don't have time to check it thoroughly. If it doesn't work then google the term SortableBindingList, there are lots of implementations out there.
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));
}
}
I use this simple function when adding a new row:
dataGridViewResult.Sort(dataGridViewResult.Columns[0], ListSortDirection.Descending);
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 &&
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;
}
}
There are a more simple way. You must set the data type of the column like this:
private void DataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
if (e.Column.Index == 0)
{
e.Column.ValueType = typeof(int);
e.Column.CellTemplate.ValueType = typeof(int);
}
}
or if you have the object name of column:
ColumnName.ValueType = typeof(int);
精彩评论