c# - Visual Studio 设计器不会为 `List<T>` 的 `Windows.Forms.Control` 成员生成代码

标签 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 尝试将列表内容序列化到窗体的资源文件中,而不是像 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实现接口(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/

相关文章:

c# - 如何检测是否安装了SQL Server CE 4.0

C# .NET 串行端口连接,不读取或写入

c# - 异常类型的停止 "not handled in user code"对话框

c# - 无需单独的项目即可获得 WinForm 的快捷方式

c# - 如果按下键或组合键,如何从后台程序检查?

c# - SetWindowsHookEx 并在窗体卡住时单击最小化/最大化/关闭按钮

visual-studio-2010 - TFS - 当我编辑时,文件不会自动 checkout 进行编辑

c# - 如何在 DataTable 中公开列

visual-studio - Visual Studio 2010 - 评论中的智能感知

c++ - 如何使用 scons 生成带有调试信息的 MSVC 解决方案?