我正在尝试改进Winforms项目,其中数据表行存储在ListViewItems的Tag属性中。当数据表被重构为List< T>时(或实际上包含列表的类)如果我可以通过使用ListView的子类使Tag属性通用,那将极大地帮助。
在最好的世界中,我希望Tag属性被公共T标签替换{get; set;}包装base.Tag并强制转换它。 第二好的将是Obsoleting Tag并提供类似TypedTag的新属性,如上所述。
我认为这将涉及至少ListView,ListViewItemCollection,SelectedListViewItemCollection和ListViewItem的子类化或复合聚合,我不知道该怎么做。
简而言之:
ListView<Employee> lvwEmployees;
应该可以实现:
Employee selected = lvwEmployees.SelectedItems[0].TypedTag;
并为此提出编译错误:
DataRow selected = lvwEmployees.SelectedItems[0].TypedTag;
有可能吗?它已经完成了吗? 项目是dotnet 2.0,但我认为如果有帮助,我会尝试升级它。
编辑:事实证明,所有者构造函数参数是某个集合需要连接到内部集合。因此,以下工作:
ListView a = new ListView();
a.Items.Add("Hello");
Assert.AreEqual(1, new ListView.ListViewItemCollection(a).Count);
这使得创建通用标记ListView变得相当容易。我稍后会发布完整的解决方案。 :)
EDIT2:这是解决方案: http://thecarlr.blogspot.com/2010/11/generic-listview.html
EDIT3:对于设计器支持,只需添加一个非泛型子类并使用它。 示例:如果您打算使用ListView&lt; Employee&gt;在表单中,创建一个ListViewEmployee:ListView&lt; Employee&gt;在另一个文件中,并使用表单中的ListViewEmployee。
添加其中一个theese listviews的最简单方法是将正常的listview添加到表单中,然后在源文件中更改它的类型。 (如果您不知道声明或实例化的位置,请找出或使用正常的列表视图。)
答案 0 :(得分:1)
你犯了错误的类通用。 SelectedItems [0]是ListViewItem,而不是ListView。
您无法更改Items和SelectedItems属性的类型。您当然可以从ListViewItem派生自己的类,只需添加要存储的属性。不需要另一个Tag属性。添加它们没有问题,但是当你从Selected / Items集合中检索它们时,你需要转回到派生类。
通常,通过仅将ListView用作模型视图来避免使用此类代码。然后,ListViewItem.Index应始终很好地从模型中获取类型安全引用。
答案 1 :(得分:0)
答案 2 :(得分:0)
VS Designer根本无法处理抽象或通用控件(not for want of asking)。
绕过该限制的一种方法是围绕标准ListView
编写类型安全包装。
这样的事情:
public class TypedListView<T> where T : class
{
public TypedObjectListView(ListView lv) {
this.lv = lv;
}
private ListView lv;
public virtual T SelectedObject {
get { return (T)this.lv.SelectedItems[0].Tag; }
}
// Lots more methods/properties
}
您在Designer中创建了一个普通的ListView,然后当您想要访问它时,您可以创建并使用您的适配器。像这样:
var typedListView = new TypedListView<Employee>(this.listView1);
Employee selectedEmployee = typedListView.SelectedObject;
您需要提供您想要使用的每个ListView
属性或方法的类型版本。
ObjectListView项目采用这种方法创建一个TypedObjectListView
,它可以完全满足您的要求。