Visual Studio设计器不为`Windows.Forms.Control` </t>的`List <t>`成员生成代码

时间:2015-01-27 23:50:01

标签: c# winforms visual-studio-2010 visual-studio-designer

以下类(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尝试将列表内容序列化为Form的资源文件,而不是创建用于实例化每个项目的代码,然后像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});

我尝试搜索ListViewListViewItem来解决问题, ListView有一个名为ListViewItemCollection的“自己的列表类”,它实现了接口IList, ICollection, IEnumerable,但List<T>实现了相同的接口。

我是否需要为它实现自定义序列化?也许这只是序列化到资源文件。我找不到太多文档,因为它没有继承任何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实现自定义序列化一样可以提供帮助。

1 个答案:

答案 0 :(得分:1)

有必要为班级实施TypeConverter。这个TypeConverter做的只是返回类的构造函数描述符。

另外,使用参数TypeConverter指定班级的[TypeConverter(typeof(typeConverter))]

根据MSDN How to: Implement a Type Converter,更具体地说,是在运行时生成属性初始化代码的类型转换器

  

.NET Framework提供了生成动态的功能   属性初始化代码在设计时将初始化a   在运行时的财产。

     

开发人员可以构建一个生成基于构造函数的类型转换器   初始化代码。这些类型转换器可以生成构造函数   使用在设计时设置的值动态编码以进行配置   运行时类型的属性。类型转换器实现了   用于配置构造函数的类型和值的逻辑   属性。

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

  

如果除了构造函数之外还需要生成代码来初始化a   属性,可以通过实现动态生成代码   自定义CodeDomSerializer并应用DesignerSerializerAttribute   将CodeDomSerializer与类型相关联的类型。这个   方法通常仅用于动态的场景   用于组件初始化的受控或定制代码生成   很重要有关此方法的更多信息,请参阅   CodeDomSerializer的文档。

也就是说,使用answer方法,需要在构造函数参数上传递属性值。如果还不够(比如设置属性不在构造函数上),则可能需要使用CodeDomSerializer,如@Octopoid所说。