【问题标题】:How to make a User control property of type Collection<MyClass> editable in Form Designer?如何在表单设计器中使 Collection<MyClass> 类型的用户控件属性可编辑?
【发布时间】:2011-11-18 05:12:08
【问题描述】:

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

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

我有一个UserControl1,具有Collection&lt;Class1&gt; 类型的字段和相应的属性Collection&lt;Class1&gt; 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 放到一个随机表单上并更改Prop 属性。出现一个通用的“集合编辑器”,就像用于列表视图控件中的列和组的那个。我可以按预期输入数据。但是,当我单击确定时,数据消失了。

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

但这只能工作一次。在编辑某些内容后打开我使用UserControl1 的表单设计器时,它给了我一个错误:

Object of type 'userctltest.Class1[]' cannot be converted to type 'userctltest.Class1[]'.

嗯。错误列表说:

Warning: ResX file Object of type 'userctltest.Class1[]' cannot be converted to type 'userctltest.Class1[]'. Line 134, position 5. cannot be parsed.

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

现在可以使用我的UserControl1 再次显示表单。 Collection 属性可编辑的,并且正在保存。它确实有效。一次。每当我更改某些内容然后尝试再次打开表单的设计器时,都会再次出现上述错误。我可以删除 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); }

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

抱歉,顺便说一句,把这篇写得像一部糟糕的恐怖小说。

【问题讨论】:

    标签: c# .net visual-studio-2010 properties designer


    【解决方案1】:

    您想要的是 CodeDom 序列化的设计时支持。您不需要SerializableAttributeISerializable,它们用于二进制序列化。 既然你想序列化集合,你必须告诉设计者序列化它。这是通过DesignerSerializationVisibiliby 属性完成的——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; }
        }
    }
    

    ...它应该可以解决问题。哦,集合属性通常是不可写的,尽管这不是强制性的。但是序列化程序希望集合属性被初始化,这就是为什么您必须为该字段添加初始化。 另外注意,如果你不希望你的属性在属性编辑器中被标记为粗体,你可以通过一个特殊的方法ShouldSerializePropertyName指定一个更复杂的“默认值”,它甚至可以是私有的。像这样:

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

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

    【讨论】:

    • 这似乎奏效了。虽然当我第一次尝试它时,设计师再次大吃一惊(等等不可序列化等等)。经过一个小时的摆弄最终没有真正改变任何东西(我检查了颠覆)它完美地工作。这是有史以来最奇怪的事情:/谢谢
    • 如果您的用户控件与表单在同一个项目中,那么您必须在使用用户控件之前构建项目。 Designer 会查看已编译的程序集,而不是您的代码。
    【解决方案2】:

    完美的例子是这样的:

    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; }
        }
    

    【讨论】:

      【解决方案3】:

      只需将Collection&lt;&gt; 更改为List&lt;&gt;

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 2011-01-06
        • 1970-01-01
        • 2016-03-08
        相关资源
        最近更新 更多