Is it possible to bind a List to a ListView in WinForms?

后端 未结 4 555
深忆病人
深忆病人 2020-12-02 00:06

I\'d like to bind a ListView to a List. I\'m using this code:

somelistview.DataBindings.Add (\"Items\", someclass, \"SomeList\");
         


        
4条回答
  •  长情又很酷
    2020-12-02 00:35

    I use the following technique to bind data to a ListView.

    It supports proper (not text-based) sorting. In the case above, by string, DateTime and integer.

    The ListView above was generated with this code:

    var columnMapping = new List<(string ColumnName, Func ValueLookup, Func DisplayStringLookup)>()
    {
        ("Name", person => person.Name, person => person.Name),
        ("Date of birth", person => person.DateOfBirth, person => $"{person.DateOfBirth:dd MMM yyyy}"),
        ("Height", person => person.HeightInCentimetres, person => Converter.CentimetresToFeetInchesString(person.HeightInCentimetres))
    };
    
    var personListview = new ListViewEx(columnMapping)
    {
        FullRowSelect = true,
        View = View.Details,
        Left = 20,
        Top = 20,
        Width = 500,
        Height = 300,                
    };
    
    var people = new[]
    {
        new Person("Cathy Smith", DateTime.Parse("1980-05-15"), 165),
        new Person("Bill Wentley", DateTime.Parse("1970-10-30"), 180),
        new Person("Alan Bridges", DateTime.Parse("1990-03-22"), 190),
    };
    
    personListview.AddRange(people);
    
    Controls.Add(personListview);
    

    In the column mapping, you'll notice that you have to specify how to get the item's value (for sorting) as well as a string (for displaying).

    Full source:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace GUI
    {
        public class ListViewEx : ListView
        {
            public ListViewEx(IList<(string ColumnName, Func ValueLookup, Func DisplayStringLookup)> columnInfo) : base()
            {
                ColumnInfo = columnInfo;
                DoubleBuffered = true;
    
                //Create the columns
                columnInfo
                    .Select(ci => ci.ColumnName)
                    .ToList()
                    .ForEach(columnName =>
                    {
                        var col = Columns.Add(columnName);
                        col.Width = -2;
                    });
    
                //Add the sorter
                lvwColumnSorter = new ListViewColumnSorter(columnInfo);
                ListViewItemSorter = lvwColumnSorter;
                ColumnClick += ListViewEx_ColumnClick;
            }
    
            IList<(string ColumnName, Func ValueLookup, Func DisplayStringLookup)> ColumnInfo { get; }
    
            private readonly ListViewColumnSorter lvwColumnSorter;
    
            public void Add(T item)
            {
                var lvi = Items.Add("");
                lvi.Tag = item;
    
                RefreshContent();
            }
    
            public void AddRange(IList items)
            {
                foreach (var item in items)
                {
                    Add(item);
                }
            }
    
            public void Remove(T item)
            {
                if (item == null) return;
    
                var listviewItem = Items
                            .Cast()
                            .Select(lvi => new
                            {
                                ListViewItem = lvi,
                                Obj = (T)lvi.Tag
                            })
                            .FirstOrDefault(lvi => item.Equals(lvi.Obj))
                            .ListViewItem;
    
                Items.Remove(listviewItem);
    
                RefreshContent();
            }
    
            public List GetSelectedItems()
            {
                var result = SelectedItems
                                .OfType()
                                .Select(lvi => (T)lvi.Tag)
                                .ToList();
    
                return result;
            }
    
            public void RefreshContent()
            {
                var columnsChanged = new List();
    
                Items
                    .Cast()
                    .Select(lvi => new
                    {
                        ListViewItem = lvi,
                        Obj = (T)lvi.Tag
                    })
                    .ToList()
                    .ForEach(lvi =>
                    {
                        //Update the contents of this ListViewItem
                        ColumnInfo
                            .Select((column, index) => new
                            {
                                Column = column,
                                Index = index
                            })
                            .ToList()
                            .ForEach(col =>
                            {
                                var newDisplayValue = col.Column.DisplayStringLookup(lvi.Obj);
                                if (lvi.ListViewItem.SubItems.Count <= col.Index)
                                {
                                    lvi.ListViewItem.SubItems.Add("");
                                }
    
                                var subitem = lvi.ListViewItem.SubItems[col.Index];
                                var oldDisplayValue = subitem.Text ?? "";
    
                                if (!oldDisplayValue.Equals(newDisplayValue))
                                {
                                    subitem.Text = newDisplayValue;
                                    columnsChanged.Add(col.Index);
                                }
                            });
                    });
    
                columnsChanged.ForEach(col => { Columns[col].Width = -2; });
    
                //AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
                //AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
            }
    
            private void ListViewEx_ColumnClick(object sender, ColumnClickEventArgs e)
            {
                if (e.Column == lvwColumnSorter.ColumnToSort)
                {
                    if (lvwColumnSorter.SortOrder == SortOrder.Ascending)
                    {
                        lvwColumnSorter.SortOrder = SortOrder.Descending;
                    }
                    else
                    {
                        lvwColumnSorter.SortOrder = SortOrder.Ascending;
                    }
                }
                else
                {
                    lvwColumnSorter.ColumnToSort = e.Column;
                    lvwColumnSorter.SortOrder = SortOrder.Ascending;
                }
    
                Sort();
            }
        }
    
        public class ListViewColumnSorter : IComparer
        {
            public ListViewColumnSorter(IList<(string ColumnName, Func ValueLookup, Func DisplayStringLookup)> columnInfo)
            {
                ColumnInfo = columnInfo;
            }
    
            public int Compare(object x, object y)
            {
                if (x == null || y == null) return 0;
    
                int compareResult;
    
                var listviewX = (ListViewItem)x;
                var listviewY = (ListViewItem)y;
    
                var objX = (T)listviewX.Tag;
                var objY = (T)listviewY.Tag;
    
                if (objX == null || objY == null) return 0;
    
                var valueX = ColumnInfo[ColumnToSort].ValueLookup(objX);
                var valueY = ColumnInfo[ColumnToSort].ValueLookup(objY);
    
                compareResult = Comparer.Default.Compare(valueX, valueY);
    
                if (SortOrder == SortOrder.Ascending)
                {
                    return compareResult;
                }
                else if (SortOrder == SortOrder.Descending)
                {
                    return -compareResult;
                }
                else
                {
                    return 0;
                }
            }
    
            public int ColumnToSort { get; set; } = 0;
    
            public SortOrder SortOrder { get; set; } = SortOrder.Ascending;
    
            public IList<(string ColumnName, Func ValueLookup, Func DisplayStringLookup)> ColumnInfo { get; }
        }
    }
    

提交回复
热议问题