2023年5月

    
public class ListView2Handler<T> where T : class
{
    private List<T> List { get; set; }
    private ListView ListView { get; set; }

    public event ColumnClickEventHandler ColClick;
    public ListView2Handler(ListView listView)
    {
        this.List = new List<T>();
        this.ListView = listView;
        this.ListView.VirtualMode = true;
        this.ListView.RetrieveVirtualItem += ListView_RetrieveVirtualItem;

        this.ListView.ColumnClick += ListView_ColumnClick;
    }

    private void ListView_ColumnClick(object sender, ColumnClickEventArgs e)
    {
        if (this.ColClick != null)
        {
            this.ListView.Sorting = this.ListView.Sorting == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
            this.OnColClick(e);
        }
    }

    public virtual void OnColClick(ColumnClickEventArgs e)
    {
        for (int i = 0; i < this.ListView.Columns.Count; i++)
        {
            var text = this.ListView.Columns[i].Text;//
            text = text.Replace("▽", "").Replace("△", "").Trim();

            if (i == e.Column)
            {
                if (this.ListView.Sorting == SortOrder.Ascending)
                {
                    text += "△";
                }
                else
                {
                    text += "▽";
                }
            }
            this.ListView.Columns[i].Text = text;
        }
        this.ListView.AutoResizeColumn(e.Column, ColumnHeaderAutoResizeStyle.HeaderSize);

        this.ColClick?.Invoke(this.ListView, e);
    }


    private void ListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
        if (List.Any() && e.ItemIndex <= List.Count)
        {
            var mode = this.List[e.ItemIndex];
            var item = GetListViewItems(mode, e.ItemIndex);
            if (e.ItemIndex % 2 == 0)
            {
                item.BackColor = Color.FromArgb(250, 250, 240);
            }
            e.Item = item;
        }
    }

    public void ShowColumHeader()
    {
        var ps = typeof(T).GetProperties();
        if (ps != null)
        {
            foreach (var p in ps)
            {
                var attr = p.GetCustomAttribute<HanderDescriptionAttribute>();
                if (attr != null)
                {
                    if (attr == null)
                        continue;
                    ColumnHeader header = new ColumnHeader();
                    header.Text = attr.Name;
                    header.Tag = p.Name;
                    ListView.Columns.Add(header);
                }
            }
        }

    }
    public void ClearData()
    {
        List.Clear();
        ListView.Invoke(new MethodInvoker(() =>
        {
            ListView.VirtualListSize = List.Count;
            ListView.Invalidate();
        }));
    }
    public void LoadData(IEnumerable<T> datas)
    {
        ClearData();
        if (datas == null)
            return;
        this.List.AddRange(datas);
        ListView.Invoke(new MethodInvoker(() =>
        {
            ListView.VirtualListSize = List.Count;
            ListView.Invalidate();
            this.ListView.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
        }));
    }
    public void RemoveItem(T item)
    {
        this.List.Remove(item);
        this.ListView.VirtualListSize = List.Count;
        this.ListView.Invalidate();
        //this.listView.Refresh();
    }

    public List<T> Filter(Predicate<T> predicate)
    {
        return this.List.FindAll(predicate);
    }

    //public void Sort(Func<T, object> predicate)
    public void Sort(Func<T, object> func)
    {
        var comparer = new ListViewItemComparer<T>(func, Comparer<object>.Default, this.ListView.Sorting);
        this.List.Sort(comparer);
        this.ListView.Invalidate();
    }

    public void EditData(T objItem)
    {
        var model = this.List.FindIndex(m => m == objItem);
        if (model > -1)
        {
            this.List[model] = objItem;
        }
        this.ListView.Invalidate();

    }
    public ListViewItem GetFouseItem()
    {
        return this.ListView.FocusedItem;
    }

    public T GetSelectData()
    {
        var d = this.ListView.FocusedItem;
        if (d != null)
        {
            return (T)this.ListView.FocusedItem.Tag;
        }
        return default(T);
    }

    public IEnumerable<T> GetSelectValues()
    {
        var ids = this.ListView.SelectedIndices;
        for (int i = 0; i < ids.Count; i++)
        {
            yield return this.List[ids[i]];
        }

    }

    private ListViewItem GetListViewItems(T model, int index)
    {
        var ps = model.GetType().GetProperties();
        var item = new ListViewItem();
        item.Tag = model;
        foreach (var p in ps)
        {
            var da = p.GetCustomAttribute<HanderDescriptionAttribute>();
            if (da == null)
                continue;

            var value = p.GetValue(model);
            if (da.IsPrimary)
            {
                //if (index > 0 && value != null && p.PropertyType == typeof(int))
                //{
                //    p.SetValue(model, index);
                //}

                if (value == null || (value.GetType() == typeof(int) && (int)value == 0))
                {
                    item.Text = index + da?.ExStr;
                    continue;
                }
                item.Text = value?.ToString() + da?.ExStr;
                continue;
            }
            item.SubItems.Add(value?.ToString() + da?.ExStr);
        }

        return item;
    }
}

public class ListViewItemComparer : IComparer
{
    private int col;
    private SortOrder order;
    public ListViewItemComparer(int column, SortOrder sortOrder)
    {
        col = column;
        order = sortOrder;
    }
    public int Compare(object x, object y)
    {
        int returnVal = -1;

        // 按字符串排序
        string strX = ((ListViewItem)x).SubItems[col].Text;
        string strY = ((ListViewItem)y).SubItems[col].Text;

        returnVal = String.Compare(strX, strY);

        // 根据排序方式反转结果
        if (order == SortOrder.Descending)
        {
            returnVal *= -1;
        }

        return returnVal;
    }
}
public class ListViewItemComparer<T> : IComparer<T> where T : class
{
    private Func<T, object> _keySelector;
    private IComparer<object> _valueComparer;
    private readonly SortOrder sortOrder;

    public ListViewItemComparer(Func<T, object> keySelector, IComparer<object> valueComparer, SortOrder sortOrder)
    {
        _keySelector = keySelector;
        _valueComparer = valueComparer;
        this.sortOrder = sortOrder;
    }


    public int Compare(T x, T y)
    {
        object xValue = _keySelector(x);
        object yValue = _keySelector(y);

        var returnVal= _valueComparer.Compare(xValue, yValue);
        // 根据排序方式反转结果
        if (sortOrder == SortOrder.Descending)
        {
            returnVal *= -1;
        }
        return returnVal;
    }
}
public class HanderDescriptionAttribute : Attribute
{
    public string Name { get; set; }
    public bool IsPrimary { get; set; }
    public string ExStr { get; set; }
}