C# 如何创建集合类型的用户控件属性<;MyClass>;在表单设计器中可编辑?

C# 如何创建集合类型的用户控件属性<;MyClass>;在表单设计器中可编辑?,c#,.net,visual-studio-2010,properties,designer,C#,.net,Visual Studio 2010,Properties,Designer,今天在工作中,我偶然发现了一个让我发疯的问题 基本上,我的目标是: 我有一个UserControl1,其中有一个类型为Collection的字段和一个相应的属性Collection Prop。像这样: public class UserControl1 : UserControl { private Collection<Class1> field = null; // later changed to: //private Collection<Class1

今天在工作中,我偶然发现了一个让我发疯的问题

基本上,我的目标是:

我有一个
UserControl1
,其中有一个类型为
Collection
的字段和一个相应的属性
Collection Prop
。像这样:

public class UserControl1 : UserControl
{
    private Collection<Class1> field = null;
    // later changed to:
    //private Collection<Class1> field = new Collection<Class1>();
    [Category("Data")]
    [DefaultValue(null)]
    [Description("asdf")]
    public Collection<Class1> prop
    {
        get { return field; }
        set { field = value; }
    }
}
如果你已经知道我搞砸了什么,那就不必读剩下的了。我要描述一下我到底做了什么

现在,我将
UserControl
放在一个随机表单上,并更改
Prop
属性。此时会出现一个通用的“集合编辑器”,与listview控件中用于列和组的编辑器类似。我可以按预期输入数据。但是,当我单击“确定”时,数据就消失了

我花了一个多小时才明白我实际上必须实例化我的字段:
private Collection field=new Collection()。很好,只是设计师进入了超级Pazzing模式。层叠噩梦错误消息,可以简化为:“您必须将
[Serializable]
放在
Class1
之前”,这样做之后,我实际上可以再次将我的
UserControl1
放在表单上

但这只起作用一次。在编辑某些内容后打开我使用
UserControl1
的窗体设计器时,它会给我一个错误:

无法将“userctltest.Class1[]”类型的对象转换为“userctltest.Class1[]”类型。

嗯。错误列表显示:

警告:无法将“userctltest.Class1[]”类型的ResX文件对象转换为“userctltest.Class1[]”类型。第134行,位置5。无法分析。

设计器尝试从resx文件获取属性的数据。删除resx文件只会“解决”一次

现在可以使用my
UserControl1
再次显示表单。集合属性是可编辑的,并且正在保存。它确实有效。一旦每当我更改某些内容,然后再次尝试打开窗体的设计器时,上述错误就会再次发生。我可以删除resx文件,但这当然也会删除我的数据

到目前为止帮助我的相关资源(在大量不太有用的搜索结果中):





(我还尝试实现ISerializable并用

{info.AddValue(“testbool”,testbool);info.AddValue(“testint”,testint);}

也没有帮助(我还尝试了属性名而不是字段名))


很抱歉把它写成一本糟糕的恐怖小说。

顺便说一句,您需要的是对CodeDom序列化的设计时支持。您不需要
SerializableAttribute
ISerializable
,这些都是用于二进制序列化的。 因为您想要序列化集合,所以必须告诉设计器将其序列化。这是通过
Content
的属性值完成的,它告诉设计器序列化属性内容,而不是属性本身。属性的内容当然应该是CodeDom序列化的,默认情况下,具有简单属性的简单类是可序列化的

因此,如果您像这样更改
UserControl1
类:

public class UserControl1 : UserControl
{
    private Collection<Class1> field = new Collection<Class1>();

    [Category("Data")]
    [Description("asdf")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public Collection<Class1> prop
    {
        get { return field; }
    }
}

现在,您的属性只有在不为空时才会显示为粗体。但我离题了,这不是一个问题:)

完美的例子是:

public partial class SCon : UserControl
    {
        public SCon()
        {
            InitializeComponent();
            if (Persoanas == null)
            {
                Persoanas = new List<Persoana>();
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<Persoan> Persoanas { get; set; }

    }

    [Serializable]
    public class Persoan   
    {
        public int Id { get; set; }
        public String Name { get; set; }
    }
公共部分类SCon:UserControl
{
公共SCon()
{
初始化组件();
if(Persoanas==null)
{
Persoanas=新列表();
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
公共列表Persoanas{get;set;}
}
[可序列化]
公营人员
{
公共int Id{get;set;}
公共字符串名称{get;set;}
}

只需将
收藏
更改为
列表

,这似乎很有效。虽然当我第一次尝试它的时候,设计师又突然冒出来了(废话,不可序列化废话)。经过一个小时的摆弄,最终没有改变任何东西(我检查了subversion),它工作得完美无缺。这是有史以来最奇怪的事情:/Thank如果您的用户控件与表单位于同一个项目中,那么您必须在使用用户控件之前构建项目。设计器查看已编译的程序集,而不是您的代码。
private bool ShouldSerializeprop() 
{
    return (field.Count > 0);
}
public partial class SCon : UserControl
    {
        public SCon()
        {
            InitializeComponent();
            if (Persoanas == null)
            {
                Persoanas = new List<Persoana>();
            }
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<Persoan> Persoanas { get; set; }

    }

    [Serializable]
    public class Persoan   
    {
        public int Id { get; set; }
        public String Name { get; set; }
    }