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文件只会“解决”一次
现在可以使用myUserControl1
再次显示表单。集合属性是可编辑的,并且正在保存。它确实有效。一旦每当我更改某些内容,然后再次尝试打开窗体的设计器时,上述错误就会再次发生。我可以删除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; }
}