как сортировать целые числа в listview
Как сортировать столбцы целых чисел в ListView
c#, .net 2.0, Winform
6 ответов
вот как я добился возможности сортировать по нескольким столбцам и сортировать каждый столбец как число или как текст.
сначала используйте этот класс:
class Sorter : System.Collections.IComparer
{
public int Column = 0;
public System.Windows.Forms.SortOrder Order = SortOrder.Ascending;
public int Compare(object x, object y) // IComparer Member
{
if (!(x is ListViewItem))
return (0);
if (!(y is ListViewItem))
return (0);
ListViewItem l1 = (ListViewItem)x;
ListViewItem l2 = (ListViewItem)y;
if (l1.ListView.Columns[Column].Tag == null)
{
l1.ListView.Columns[Column].Tag = "Text";
}
if (l1.ListView.Columns[Column].Tag.ToString() == "Numeric")
{
float fl1 = float.Parse(l1.SubItems[Column].Text);
float fl2 = float.Parse(l2.SubItems[Column].Text);
if (Order == SortOrder.Ascending)
{
return fl1.CompareTo(fl2);
}
else
{
return fl2.CompareTo(fl1);
}
}
else
{
string str1 = l1.SubItems[Column].Text;
string str2 = l2.SubItems[Column].Text;
if (Order == SortOrder.Ascending)
{
return str1.CompareTo(str2);
}
else
{
return str2.CompareTo(str1);
}
}
}
}
в конструкторе формы установите сортировщик следующим образом:
lvSeries.ListViewItemSorter = new Sorter();
затем обработайте ColumnClick даже вашего элемента управления listview следующим образом:
private void lvSeries_ColumnClick(object sender, ColumnClickEventArgs e)
{
Sorter s = (Sorter)lvSeries.ListViewItemSorter;
s.Column = e.Column;
if (s.Order == System.Windows.Forms.SortOrder.Ascending)
{
s.Order = System.Windows.Forms.SortOrder.Descending;
}
else
{
s.Order = System.Windows.Forms.SortOrder.Ascending;
}
lvSeries.Sort();
}
Это все зависит от свойства тега каждого столбца, либо установленного на "числовое", либо нет, поэтому сортировщик знает, как сортировать.
В приведенном выше примере я бросил значения как поплавки, когда числовые, вы можете изменить это на int.
Если вы начинаете работу с ListView, ваша жизнь будет намного проще, если вы используете ObjectListView вместо. ObjectListView-это оболочка с открытым исходным кодом вокруг .NET WinForms ListView, и она решает все эти раздражающие небольшие проблемы, которые обычно делают работу с ListView настолько разочаровывающей. Например, он автоматически сортирует ints так, что " 100 "приходит после" 3 " (даты, bools, и все остальное сортируется правильно).
серьезно, вы никогда не будете хотите вернуться к простому ListView после использования ObjectListView.
Да, я автор, но это не значит, что я предвзят... Ладно, ну может и так:) Look здесь для мнения некоторых других людей.
вам нужно будет создать класс, который реализует IComparer
интерфейс (не универсальный). В этом классе вы читаете Text
свойство из правильного подпункта, преобразуйте его в int и выполните сравнение:
public class IntegerComparer : IComparer
{
private int _colIndex;
public IntegerComparer(int colIndex)
{
_colIndex = colIndex;
}
public int Compare(object x, object y)
{
int nx = int.Parse((x as ListViewItem).SubItems[_colIndex].Text);
int ny = int.Parse((y as ListViewItem).SubItems[_colIndex].Text);
return nx.CompareTo(ny);
}
}
затем вы назначаете такой компаратор свойству ListViewItemSorter и вызываете метод сортировки элемента управления ListView:
// create a comparer for column index 1 and assign it to the control, and sort
myListView.ListViewItemSorter = new IntegerComparer(1);
myListView.Sort();
Я бы сделал это в источнике данных (модели) вместо представления. Сортируйте его там, и он должен обновить его в представлении через привязку данных.
я использовал класс Neil-N, но изменил оператор if для проверки свойства Type вместо свойства Tag. Я установил для каждого столбца тип Number (вместо Text), в котором было целое значение. Сортировка отлично работает.
if (l1.ListView.Columns[Column].Type.ToString() == "Number")
class ListViewAutoSorter : System.Collections.IComparer
{
private int Column = 0;
private System.Windows.Forms.SortOrder Order = SortOrder.Ascending;
public ListViewAutoSorter(int Column, SortOrder Order)
{
this.Column = Column;
this.Order = Order;
}
public int Compare(object x, object y) // IComparer Member
{
if (!(x is ListViewItem))
return (0);
if (!(y is ListViewItem))
return (0);
var l1 = (ListViewItem)x;
var l2 = (ListViewItem)y;
var value1 = 0.0;
var value2 = 0.0;
if (Double.TryParse(l1.SubItems[Column].Text, out value1) &&
Double.TryParse(l2.SubItems[Column].Text, out value2))
{
if (Order == SortOrder.Ascending)
{
return value1.CompareTo(value2);
}
else
{
return value2.CompareTo(value1);
}
}
else
{
var str1 = l1.SubItems[Column].Text;
var str2 = l2.SubItems[Column].Text;
if (Order == SortOrder.Ascending)
{
return str1.CompareTo(str2);
}
else
{
return str2.CompareTo(str1);
}
}
}
}