[英]Is it possible to bind a List to a ListView in WinForms?
I'd like to bind a ListView to a List<string><\/code> .
我想将 ListView 绑定到
List<string><\/code> 。
I'm using this code:
我正在使用这段代码:
somelistview.DataBindings.Add ("Items", someclass, "SomeList");
The ListView class does not support design time binding. ListView 类不支持设计时绑定。 An alternative is presented in this project .
本项目提供了一种替代方案。
Nice binding implementation for ListView不错的 ListView 绑定实现
http://www.interact-sw.co.uk/utilities/bindablelistview/source/ http://www.interact-sw.co.uk/utilities/bindablelistview/source/
Alternatively, you can use DataGridView if you want data binding.或者,如果需要数据绑定,可以使用 DataGridView。 Using BindingList and BindingSource will update your DataGrid when new item is added to your list.
当新项目添加到您的列表时,使用 BindingList 和 BindingSource 将更新您的 DataGrid。
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; }
}
I use the following technique to bind data to a ListView.我使用以下技术将数据绑定到 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:上面的 ListView 是用以下代码生成的:
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; }
}
}
Adding to the answer by @Fidel<\/a>通过@Fidel 添加到答案<\/a>
using System.Reflection;
public ListViewEx() : this(AutoMapColumns()) { }
private static List<(string ColumnName, Func<T, object> ValueLookup, Func<T, string> DisplayStringLookup)> AutoMapColumns()
{
var mapping = new List<(string ColumnName, Func<T, object> ValueLookup, Func<T, string> DisplayStringLookup)>();
var props = typeof(T).GetTypeInfo().GetProperties();
foreach (var prop in props)
{
mapping.Add((
prop.Name,
(T t) => prop.GetValue(t),
(T t) => prop.GetValue(t).ToString()
));
}
return mapping;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.