最近專案需要實作串列排序,由于是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; }
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/40656.html
標籤:C#
