c# – 如何使Form类型的用户控件属性可在Form Designer中编辑?

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

基本上我的目标是这样的:

我有一个UserControl1,一个类型为Collection< Class1>的字段和相应的属性集合< Class1> 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; }
    }
}
// later added:
//[Serializable]
public class Class1
{
    private bool booltest; public bool Booltest { get...set...}
    private int inttest; public int Inttest { get...set...}
}

如果你已经知道我搞砸了什么:不需要阅读其余的内容.我要描述我究竟做了什么

现在我把UserControl放在一个随机的Form中,并改变了Prop属性.出现一个通用的“集合编辑器”,就像列表视图控件中的列和组一样.我可以按预期输入数据.但是,当我单击确定,数据已经消失.

我花了一个多小时才弄清楚,我实际上必须实例化我的字段:private Collection< MyClass> field = new Collection< MyClass>();.非常好,只有设计师进入超级喷雾模式.级联的噩梦错误消息可以减少为:“您必须将[Serializable]放在Class1之前.做完之后,我可以把我的UserControl1放在Form上了.

但这只能奏效一次.当打开Form的设计者时,我在使用UserControl1后,编辑一些东西,它给我一个错误

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

好.错误列表说:

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

设计人员尝试从resx文件获取属性的数据.删除resx文件解决”一次.

现在可以使用我的UserControl1再次显示该表单. Collection属性是可编辑的,并且正在被保存.它实际上是有效的.一旦.每当我改变一些东西,然后再次尝试打开Form的设计师,上面的错误再次出现.我可以删除resx文件,但这当然也会删除我的数据.

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

http://www.codeproject.com/Answers/190675/Usercontrol-with-custom-class-property#answer1
http://www.codeproject.com/KB/cs/propertyeditor.aspx
http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=94
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx

(我也尝试实现ISerializable并覆盖GetobjectData

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

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

对不起,写这个像一个坏的恐怖小说btw.

解决方法

您想要的是使用CodeDom序列化的设计时间支持.您不需要SerializableAttribute或ISerializable,那些用于二进制序列化.
既然你想序列化集合,你必须告诉设计者把它序列化.这是通过 DesignerSerializationVisibiliby属性 – 值的内容来告诉设计者序列化属性内容而不是属性本身.属性内容当然应该是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; }
    }
}

…应该做的伎俩哦和收藏属性通常是不可写的,虽然这不是强制性的.但是串行器期望收集属性被初始化,这就是为什么你必须添加字段的初始化.
一个注意事项,如果您不希望在属性编辑器中将属性标记为粗体,则可以通过特殊方法ShouldSerializePropertyName(甚至可以是私有的)来指定更复杂的“认值”.像这样:

private bool ShouldSerializeprop() 
{
    return (field.Count > 0);
}

现在你的财产只有当它不是空时才是粗体.但我离题,这不是问题:)

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...