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

后端 未结 4 527
深忆病人
深忆病人 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:23

    Nice binding implementation for ListView

    http://www.interact-sw.co.uk/utilities/bindablelistview/source/

    0 讨论(0)
  • 2020-12-02 00:29

    Alternatively, you can use DataGridView if you want data binding. Using BindingList and BindingSource will update your DataGrid when new item is added to your list.

    var barcodeContract = new BarcodeContract { Barcode = barcodeTxt.Text, Currency = currencyTxt.Text, Price = priceTxt.Text };
    
            list.Add(barcodeContract);
            var bindingList = new BindingList<BarcodeContract>(list);
            var source = new BindingSource(bindingList, null);
            dataGrid.DataSource = source;
    

    And data model class

        public class BarcodeContract
    {
        public string Barcode { get; set; }
        public string Price { get; set; }
        public string Currency { get; set; }
    }
    
    0 讨论(0)
  • 2020-12-02 00:30

    The ListView class does not support design time binding. An alternative is presented in this project.

    0 讨论(0)
  • 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<Person, object> ValueLookup, Func<Person, string> 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<Person>(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<T> : ListView
        {
            public ListViewEx(IList<(string ColumnName, Func<T, object> ValueLookup, Func<T, string> 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<T>(columnInfo);
                ListViewItemSorter = lvwColumnSorter;
                ColumnClick += ListViewEx_ColumnClick;
            }
    
            IList<(string ColumnName, Func<T, object> ValueLookup, Func<T, string> DisplayStringLookup)> ColumnInfo { get; }
    
            private readonly ListViewColumnSorter<T> lvwColumnSorter;
    
            public void Add(T item)
            {
                var lvi = Items.Add("");
                lvi.Tag = item;
    
                RefreshContent();
            }
    
            public void AddRange(IList<T> items)
            {
                foreach (var item in items)
                {
                    Add(item);
                }
            }
    
            public void Remove(T item)
            {
                if (item == null) return;
    
                var listviewItem = Items
                            .Cast<ListViewItem>()
                            .Select(lvi => new
                            {
                                ListViewItem = lvi,
                                Obj = (T)lvi.Tag
                            })
                            .FirstOrDefault(lvi => item.Equals(lvi.Obj))
                            .ListViewItem;
    
                Items.Remove(listviewItem);
    
                RefreshContent();
            }
    
            public List<T> GetSelectedItems()
            {
                var result = SelectedItems
                                .OfType<ListViewItem>()
                                .Select(lvi => (T)lvi.Tag)
                                .ToList();
    
                return result;
            }
    
            public void RefreshContent()
            {
                var columnsChanged = new List<int>();
    
                Items
                    .Cast<ListViewItem>()
                    .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<T> : IComparer
        {
            public ListViewColumnSorter(IList<(string ColumnName, Func<T, object> ValueLookup, Func<T, string> 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<T, object> ValueLookup, Func<T, string> DisplayStringLookup)> ColumnInfo { get; }
        }
    }
    
    0 讨论(0)
提交回复
热议问题