最近項目需要實現列表排序,由於是winform的,並使用了ListView列表控制項,並且第一列顯示了序號,要求:點擊每列標題實現列表排序,並且序號列要跟隨排序後的數據顯示。 查看了微軟的官方文檔,ListView沒有實現針對某列不參與排序的功能,在DataGridView中就有實現,考慮到更換控制項可 ...
最近項目需要實現列表排序,由於是winform的,並使用了ListView列表控制項,並且第一列顯示了序號,要求:點擊每列標題實現列表排序,並且序號列要跟隨排序後的數據顯示。
查看了微軟的官方文檔,ListView沒有實現針對某列不參與排序的功能,在DataGridView中就有實現,考慮到更換控制項可能付出的代價,決定還是繼續用ListView實現,實現的思路大致如下:將ListView中的每一項轉換成實體添加到List中,針對這個實體類實現Compare並繼承ICompare介面,實現ListView的ColumnClick事件,在事件處理函數中獲取點擊的列名,並以此作為排序依據,主要代碼如下:
private List<ListViewItemModel> _viewItemList = new List<ListViewItemModel>();//存儲待排序實體
private ListViewColumnSorter lvwColumnSorter = new ListViewColumnSorter();//排序器
1 //列標題點擊事件處理函數 2 private void LvTag_ColumnClick(object sender, ColumnClickEventArgs e) 3 { 4 if (e.Column == 0) return;//序號列不排序 5 _viewItemList.Clear();//清空存儲ListViewItem列表 6 string colName = lvTag.Items[e.Column].SubItems[e.Column].Name;//取列名 7 foreach (ListViewItem item in lvTag.Items)//轉換實體 8 { 9 ListViewItemModel model = item.ToModel<ListViewItemModel>(); 10 if (!_viewItemList.Contains(model)) 11 _viewItemList.Add(item.ToModel<ListViewItemModel>()); 12 } 13 lvTag.Items.Clear();//清空ListView 14 if (colName == lvwColumnSorter.SortColumnName)//檢查點擊的列是不是現在的排序列. 15 { 16 if (lvwColumnSorter.Order == SortOrder.Ascending)//重新設置此列的排序方法. 17 lvwColumnSorter.Order = SortOrder.Descending; 18 else 19 lvwColumnSorter.Order = SortOrder.Ascending; 20 } 21 else 22 { 23 lvwColumnSorter.SortColumnName = colName;//設置排序列,預設為正向排序 24 lvwColumnSorter.Order = SortOrder.Ascending; 25 } 26 _viewItemList.Sort(lvwColumnSorter); 27 this.lvTag.BeginUpdate(); 28 ListViewItem[] listViewItems = new ListViewItem[_viewItemList.Count]; 29 for (int i = 0; i < _viewItemList.Count; i++) 30 { 31 ListViewItemModel model = _viewItemList[i];//將實體轉換為ListViewItem添加到ListView 32 ListViewItem item = new ListViewItem($"{i + 1}");//計算序號 33 item.Name = model.Epc;//設置Name 34 item.SubItems.Add(model.Epc).Name = "Epc"; 35 item.SubItems.Add(model.EpcLen.ToStr()).Name = "EpcLen"; 36 item.SubItems.Add(model.ReadCount.ToStr()).Name = "ReadCount"; 37 item.SubItems.Add(model.Rssi1.ToStr()).Name = "Rssi1"; 38 item.SubItems.Add(model.RssiAvg1.ToStr()).Name = "RssiAvg1"; 39 item.SubItems.Add(model.Rssi2.ToStr()).Name = "Rssi2"; 40 item.SubItems.Add(model.RssiAvg2.ToStr()).Name = "RssiAvg2"; 41 item.SubItems.Add(model.Rssi3.ToStr()).Name = "Rssi3"; 42 item.SubItems.Add(model.RssiAvg3.ToStr()).Name = "RssiAvg3"; 43 item.SubItems.Add(model.Rssi4.ToStr()).Name = "Rssi4"; 44 item.SubItems.Add(model.RssiAvg4.ToStr()).Name = "RssiAvg4"; 45 item.SubItems.Add(model.Tid).Name = "Tid"; 46 item.SubItems.Add(model.TidLen.ToStr()).Name = "TidLen"; 47 lvTag.Items.Add(item);//添加到列表 48 } 49 }
//ListViewColumnSorter 定義
public class ListViewColumnSorter : IComparer<ListViewItemModel>
{
private string _sortColumnName;// 指定按照哪個列排序
private CaseInsensitiveComparer _objectCompare;// 聲明CaseInsensitiveComparer類對象,
public ListViewColumnSorter()
{
_sortColumnName = string.Empty;// 預設按第一列排序
Order = SortOrder.None;// 排序方式為不排序
_objectCompare = new CaseInsensitiveComparer();// 初始化CaseInsensitiveComparer類對象
}
public int Compare(ListViewItemModel x, ListViewItemModel y)
{
int compareResult;
Regex regex = new Regex(@"^\d+(\.\d+)?$");
PropertyInfo piX = x.GetType().GetProperty(_sortColumnName);
PropertyInfo piY = x.GetType().GetProperty(_sortColumnName);
if (regex.IsMatch(piX.GetValue(x).ToStr()) && regex.IsMatch(piY.GetValue(y).ToStr()))
compareResult = _objectCompare.Compare(Convert.ToDecimal(piX.GetValue(x)), Convert.ToDecimal(piY.GetValue(y)));
else
compareResult = _objectCompare.Compare(piX.GetValue(x), piY.GetValue(y));//比較
if (Order == SortOrder.Ascending)// 根據上面的比較結果返回正確的比較結果
return compareResult;// 因為是正序排序,所以直接返回結果
else if (Order == SortOrder.Descending)
return (-compareResult);// 如果是反序排序,所以要取負值再返回
else
return 0;// 如果相等返回0
}
public SortOrder Order { set; get; }//獲取或設置排序方式
public string SortColumnName { get => _sortColumnName; set => _sortColumnName = value; }
}