C# 按字母顺序对 ListView 上的项目进行排序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10779031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Alphabetically Sorting the items on a ListView
提问by Bohn
I have a listview like this and in FormLoad event I should do some initializations for it such as this: ( I need these ) .
我有一个这样的列表视图,在 FormLoad 事件中,我应该为它做一些初始化,例如:(我需要这些)。
listView.Scrollable = true;
listView.HideSelection = false;
listView.FullRowSelect = true;
listView.View = View.Details;
listView.HeaderStyle = ColumnHeaderStyle.None;
ColumnHeader header = new ColumnHeader();
header.Text = "MyHdr";
header.Name = "MyCol";
header.Width = listView.ClientSize.Width;
listView.Columns.Add(header);
and the way I am adding items to it is pretty simple like this:
我向它添加项目的方式非常简单,如下所示:
listView.Items.Add("hello");
listView.Items.Add("How are you");
//... etc
But I want them to be added and sorted alphabetically but when I add a new item to it and call Sort method, it doesn't do anything. Why?! :(
但是我希望它们按字母顺序添加和排序,但是当我向其中添加新项目并调用 Sort 方法时,它什么也不做。为什么?!:(
EDIT:This is the whole section that at its last line I am calling Sort() The goal is to have two list views, and a Move Button, when Move button is clicked the selected items from one listview should get moved to the other listview. (Both listviews don't need to be sorted. Just the AvailLV listview should be sorted )
编辑:这是我在最后一行调用 Sort() 的整个部分目标是有两个列表视图和一个移动按钮,当单击移动按钮时,一个列表视图中的选定项目应该移动到另一个列表视图. (两个列表视图都不需要排序。只需要对 AvailLV 列表视图进行排序)
private void MoveBtn_Click(object sender, EventArgs e)
{
ListView source=null;
ListView target= null;
if(AvailableLV.SelectedItems.Count>0)
{
source = AvailableLV;
target = SelectedLV;
}
if(SelectedLV.SelectedItems.Count>0)
{
source = SelectedLV;
target = AvailableLV;
}
if (source != null && target != null)
{
HaulItems(source, target);
}
}
private void HaulItems(ListView source , ListView target)
{
foreach(ListViewItem item in source.Items)
{
if(item.Selected)
{
source.Items.Remove(item);
target.Items.Add(item);
}
}
AvailableLV.Sort();
}
采纳答案by Mark Hall
Where are you setting your ListView.Sorting Property
你在哪里设置你的ListView.Sorting 属性
From above link:
从上面的链接:
The Sorting property allows you to specify whether or not items are sorted in the ListView control. By default, no sorting is performed. When the Sorting property is set to Ascending or Descending, the items in the ListView are sorted automatically in ascending alphabetical order (when the property is set to Ascending) or descending alphabetical order (when the property is set to Descending). You can use this property to automatically sort items that are displayed in your ListView control to make it easier for users to find items when a large number of items are available.
Sorting 属性允许您指定是否在 ListView 控件中对项目进行排序。默认情况下,不执行排序。当 Sorting 属性设置为 Ascending 或 Descending 时,ListView 中的项目会自动按照字母升序(当该属性设置为 Ascending)或降序(当该属性设置为 Descending)时进行排序。您可以使用此属性自动对 ListView 控件中显示的项目进行排序,以便在有大量项目可用时让用户更容易找到项目。
Looking at your edit, I think all you need to do is set the ListView.SortingProperty on AvailableLVand it will automatically sort your items as they are added. or instead of calling.
看看你的编辑,我认为你需要做的就是设置ListView.Sorting属性AvailableLV,它会在添加项目时自动对它们进行排序。或者而不是打电话。
AvailableLV.Sort();
use
用
AvailableLV.Sorting = SortOrder.Ascending;
回答by Dr Archer
If anyone pays attention to this topic, I found the easiest route is to send the listview to a datatable and create a dataview from it and then sort the dataview. After that dataview is sorted, create a temporary table and then push the rows back into the listview. Ex below.
如果有人关注这个话题,我发现最简单的方法是将列表视图发送到数据表并从中创建数据视图,然后对数据视图进行排序。在对数据视图进行排序后,创建一个临时表,然后将行推回到列表视图中。例如下面。
public string SortOrder;
public string ItemSorted;
private void LSTHistory_ColumnClick(object sender, ColumnClickEventArgs e)
{
DataTable TempTable = new DataTable();
for (int i = 0; i < LSTHistory.Columns.Count; i++)
{
TempTable.Columns.Add(LSTHistory.Columns[i].Text);
}
foreach (ListViewItem Item in LSTHistory.Items)
{
DataRow iRow = TempTable.NewRow();
iRow[0] = Item.Text;
iRow[1] = Item.SubItems[1].Text;
TempTable.Rows.Add(iRow);
}
if (SortOrder == string.Empty || SortOrder == "ASC") SortOrder = "DESC";
else SortOrder = "ASC";
if (e.Column == COLTime.Index)
{
ItemSorted = COLTime.Text;
}
else
{
ItemSorted = COLURL.Text;
}
DataView OldView = TempTable.DefaultView;
OldView.Sort = ItemSorted + " " + SortOrder;
DataTable SortedTable = OldView.ToTable();
LSTHistory.Items.Clear();
foreach (DataRow iRow in SortedTable.Rows)
{
LSTHistory.Items.Add(iRow[0].ToString()).SubItems.Add(iRow[1].ToString());
}
}
回答by TaW
Yet another later-comer to the ball-game.
又一个后来者参加了球赛。
This solution uses Linqto sort the items.
此解决方案用于Linq对项目进行排序。
It can sort by clicking the column headers. The sort is by numbers, strings or dates, it will toggle between ascending and descending and it ignores invalid data, sorting them to the beginning or end.
它可以通过单击列标题进行排序。排序是按数字、字符串或日期,它将在升序和降序之间切换,并忽略无效数据,将它们排序到开头或结尾。
You need to feed in the types of the columns in a simple string.
您需要在一个简单的字符串中输入列的类型。
static class LvHelper
{
public static void SortByColumn(this ListView lv, string colTypes,
ColumnClickEventArgs e)
{
string lvSort = "As0";
if (lv.Tag != null) lvSort = lv.Tag.ToString();
if (e.Column < 0 || e.Column > colTypes.Length - 1) return;
char sortType = colTypes[e.Column];
if (sortType == '-') return;
int mini = lv.Items.Cast<ListViewItem>().Select(x => x.SubItems.Count).Min();
if (sortType != 's' && lv.Items.Cast<ListViewItem>()
.Select(x => x.SubItems.Count - 1).Min() < e.Column) return;
int sortCol = Convert.ToInt32(lvSort.Substring(2));
bool asc = lvSort[0] == 'A';
if (e.Column == sortCol) asc = !asc;
DateTime dummyD;
double dummyN;
double maxDate = DateTime.MaxValue.ToOADate();
int order = asc ? 1 : -1;
List<ListViewItem> sorted = null;
try
{
if (sortType == 'n') // numbers
sorted = lv.Items.Cast<ListViewItem>().Select(x => x)
.OrderBy(x => order * Convert.ToDouble(
double.TryParse(x.SubItems[e.Column].Text, out dummyN)
? x.SubItems[e.Column].Text
: (double.MinValue / 2).ToString())).ToList();
else if (sortType == 'd') // dates
sorted = lv.Items.Cast<ListViewItem>().Select(x => x)
.OrderBy(x => (Convert.ToDateTime(
DateTime.TryParse(x.SubItems[e.Column].Text, out dummyD)
? x.SubItems[e.Column].Text
: "1900-01-01").ToOADate() * order)).ToList();
else // strings
{
if (asc)
sorted = lv.Items.Cast<ListViewItem>().Select(x => x)
.OrderBy(x => x.SubItems.Count -1 < e.Column
? "" : (x.SubItems[e.Column].Text)).ToList();
else sorted = lv.Items.Cast<ListViewItem>().Select(x => x)
.OrderByDescending(x => x.SubItems.Count -1 < e.Column
? "" : (x.SubItems[e.Column].Text)).ToList();
}
}
catch (ArgumentOutOfRangeException ex) { return; }
lv.Items.Clear();
lv.Items.AddRange(sorted.ToArray());
lv.Tag = "" + (asc ? "A" : "D") + sortType.ToString() + e.Column;
}
}
The solution uses the LV's Tagto remember the current sort.
该解决方案使用 LVTag来记住当前的排序。
The solution expects data to be there, so missingsubitems will make the sort fail.
该解决方案期望数据在那里,因此缺少子项将使排序失败。
It is written as an extension method, so after adding the class you can call it on any ListView:
它是作为扩展方法编写的,因此在添加类后,您可以在任何上调用它ListView:
private void someListView_ColumnClick(object sender, ColumnClickEventArgs e)
{
ListView lv = sender as ListView;
string colTypes = "sds-n"; // string, date, string, excluded, number
lv.SortByColumn(colTypes, e);
}
回答by mike_coreit
If you are only looking for a one-time sort and you have access to the data before it is added to the ListView then this is a tidy solution:
如果您只是在寻找一次性排序,并且在将数据添加到 ListView 之前您可以访问数据,那么这是一个整洁的解决方案:
string[] exampleData = { "1", "2", "3" };
string[] namesToSortBy = { "Sam", "Bill", "Jeff" };
SortedList<string, ListViewItem> alphabetical = new SortedList<string, ListViewItem>();
for (int i = 0; i < exampleData.Length; i++)
{
ListViewItem lvi = new ListViewItem();
lvi.Text = exampleData[i];
lvi.SubItems.Add(namesToSortBy[i]);
alphabetical.Add(namesToSortBy[i], lvi);
}
foreach (KeyValuePair<string, ListViewItem> item in alphabetical)
{
listView1.Items.Add(item.Value);
}

