The following class (a Windows Forms Control) is a type of list control,
and the ListControlItem
don't inherit any Windows Control class.
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; }
}
}
The problem is, at Design Time, Visual Studio tries to serialize the list content to the resource file of the Form, instead of creating the code for instantiating each item and then adding to the control like with ListView
and ListViewItem
.
Visual Studio design generated code for ListControl
:
this.listControl1.Items = ((System.Collections.Generic.List<ListControlItem>)(resources.GetObject("listControl1.Items")));
For 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});
I tried to search the ListView
and ListViewItem
to solve the problem,
ListView
has its "own list class" named ListViewItemCollection
that implements the interfaces IList, ICollection, IEnumerable
, but List<T>
implements the same interfaces.
Does I need to implement a custom serialization for it? Maybe this would just serialize to the resources file. I can't find much documentation as it don't inherit any Windows Forms Control base classes.
UPDATE
Putting the attribute [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
in the List<T>
property gives one resource for each List<T>
item.
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"))));
Thats like implementing a custom serialization for ListControlItem
can help.
It's necessary to implement a TypeConverter
for the class. What this TypeConverter
do is just returning a constructor descriptor for the class.
Also, specify the TypeConverter
of the class using the parameter [TypeConverter(typeof(typeConverter))]
.
According to MSDN How to: Implement a Type Converter in this case more specifically on the Type Converters That Generate Code for Property Initialization at Run Time.
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.
The resulting code of the Visual Studio designer
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());
The TypeConverter
return just a no parameter constructor, but that can be changed in the TypeConverter
code.
About the 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.
That is, with the answer method, the properties values need to be passed on the constructor parameters. If is not sufficient (like setting properties not on the constructor), then it may be necessary to use CodeDomSerializer
like @Octopoid said.