以下类(Windows 窗体控件)是一种列表控件,
和 ListControlItem
不要继承任何 Windows Control 类。
public class ListControl : Control
{
private List<ListControlItem> items;
public ListControl()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.items = new List<ListControlItem>();
}
public List<ListControlItem> Items
{
get { return items; }
set { items = value; }
}
}
问题是,在设计时,Visual Studio 尝试将列表内容序列化到窗体的资源文件中,而不是像 ListView
那样创建用于实例化每个项目的代码,然后添加到控件中。和 ListViewItem
.
Visual Studio 设计为 ListControl
生成的代码:
this.listControl1.Items = ((System.Collections.Generic.List<ListControlItem>)(resources.GetObject("listControl1.Items")));
对于 ListView
:
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("");
System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("");
System.Windows.Forms.ListViewItem listViewItem4 = new System.Windows.Forms.ListViewItem("");
System.Windows.Forms.ListViewItem listViewItem5 = new System.Windows.Forms.ListViewItem("");
System.Windows.Forms.ListViewItem listViewItem6 = new System.Windows.Forms.ListViewItem("");
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3,
listViewItem4,
listViewItem5,
listViewItem6});
我试图搜索 ListView
和 ListViewItem
解决问题,
ListView
有它的“自己的列表类”,名为 ListViewItemCollection
实现接口(interface) IList, ICollection, IEnumerable
,但是List<T>
实现相同的接口(interface)。
我需要为它实现自定义序列化吗?也许这只会序列化到资源文件。我找不到太多文档,因为它不继承任何 Windows 窗体控件基类。
更新
放置属性 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
在List<T>
属性为每个 List<T>
提供一个资源项目。
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items"))));
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items1"))));
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items2"))));
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items3"))));
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items4"))));
this.listControl1.Items.Add(((ListControlItem)(resources.GetObject("listControl1.Items5"))));
这就像为 ListControlItem
实现自定义序列化可以提供帮助。
最佳答案
有必要为该类实现一个TypeConverter
。这个 TypeConverter
所做的只是返回类的构造函数描述符。
此外,使用参数 [TypeConverter(typeof(typeConverter))]
指定类的 TypeConverter
。
根据 MSDN How to: Implement a Type Converter在这种情况下,更具体地说是在运行时为属性初始化生成代码的类型转换器。
The .NET Framework provides the capability to generate dynamic property initialization code at design time that will initialize a property at run time.
Developers can build a type converter that produces constructor-based initialization code. These type converters can generate constructor code dynamically using values set at design time in order to configure properties of a type at run time. The type converter implements the logic to configure the type and values of a constructor for the property.
Visual Studio 设计器的结果代码
this.listControl1.Items.Add(new ListControlItem());
this.listControl1.Items.Add(new ListControlItem());
this.listControl1.Items.Add(new ListControlItem());
this.listControl1.Items.Add(new ListControlItem());
this.listControl1.Items.Add(new ListControlItem());
this.listControl1.Items.Add(new ListControlItem());
TypeConverter
仅返回一个无参数构造函数,但这可以在 TypeConverter
代码中更改。
关于CodeDomSerializer
If you need to produce code besides a constructor to initialize a property, it is possible to dynamically generate code by implementing a custom CodeDomSerializer and applying a DesignerSerializerAttribute that associates your CodeDomSerializer for a type with the type. This approach is typically used only for scenarios in which dynamically controlled or customized code generation for component initialization is important. For more information on this approach, see the documentation for CodeDomSerializer.
也就是说,使用 answer 方法,需要将属性值传递给构造函数参数。如果还不够(比如不在构造函数上设置属性),那么可能需要使用 CodeDomSerializer
就像@Octopoid 说的那样。
关于c# - Visual Studio 设计器不会为 `List<T>` 的 `Windows.Forms.Control` 成员生成代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28182209/