Collections Editor不在VS 2013的设计视图中保留自定义Web控件标记中的条目?

时间:2016-05-20 06:27:46

标签: c# asp.net visual-studio-2013 webforms asp.net-customcontrol

我正在尝试为ASP.Net WebForms开发一个简单的自定义Web控件,该控件具有名为Subscriptions的集合属性。

我可以成功编译控件项目,并将其从工具箱添加到aspx页面,没有任何问题。

问题是当我在Visual Studio 2013的设计视图中使用集合编辑器添加Subscriptions属性的条目时。

我可以输入多个订阅,但是当我点击集合编辑器的OK按钮然后我回到设计视图中的Subscriptions属性时它就是空的,即使我刚刚输入了一些条目。

aspx中自定义控件的标记

<cc1:WebControl1 ID="WebControl1" runat="server"></cc1:WebControl1>

问题:我的代码在设计视图中导致集合没有显示在控件的标记中是不正确的?

自定义网络控制代码

namespace WebControl1
{
    [ToolboxData("<{0}:WebControl1 runat=\"server\"> </{0}:WebControl1>")]
    [ParseChildren(true)]
    [PersistChildren(false)]
    public class WebControl1 : WebControl
    {
        [Bindable(true)]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string Text
        {
            get
            {
                String s = (String)ViewState["Text"];
                return ((s == null) ? "[" + this.ID + "]" : s);
            }

            set
            {
                ViewState["Text"] = value;
            }
        }
        [
        Category("Behavior"),
        Description("The subscriptions collection"),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
        Editor(typeof(SubscriptionCollectionEditor), typeof(UITypeEditor)),
        PersistenceMode(PersistenceMode.InnerDefaultProperty)
        ]
        public List<Subscription> Subscriptions { get; set; }

        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write(Text);
        }
    }
}


[TypeConverter(typeof(ExpandableObjectConverter))]
public class Subscription
{
    private string name;
    private decimal amount;


    public Subscription()
        : this(String.Empty, 0.00m)
    {
    }

    public Subscription(string nm, decimal amt)
    {
        name = nm;
        amount = amt;
    }

    [
    Category("Behavior"),
    DefaultValue(""),
    Description("Name of subscription"),
    NotifyParentProperty(true),
    ]
    public String Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }

    [
    Category("Behavior"),
    DefaultValue("0.00"),
    Description("Amount for subscription"),
    NotifyParentProperty(true)
    ]
    public decimal Amount
    {
        get
        {
            return amount;
        }
        set
        {
            amount = value;
        }
    }
   }

public class SubscriptionCollectionEditor : System.ComponentModel.Design.CollectionEditor
{
    public SubscriptionCollectionEditor(Type type)
        : base(type)
    {
    }

    protected override bool CanSelectMultipleInstances()
    {
        return false;
    }

    protected override Type CreateCollectionItemType()
    {
        return typeof(Subscription);
    }
}

1 个答案:

答案 0 :(得分:0)

我能够通过进行2次更改来解决问题。

  1. 由于对于像List这样的集合,.Net框架会自动显示一个合适的编辑器,因此我们不需要指定编辑器,因为集合是List类型。因此,我们不需要此属性Editor(typeof(SubscriptionCollectionEditor), typeof(UITypeEditor))
  2. 需要移除Subscriptions的setter,只有get应该在那里,如下面的代码所示。如果使用了setter,则应该将其用作第二个代码段。 但是,自动获取和设置不应与自定义Web控件中的集合属性一起使用
  3. collections属性的最终代码应如下所示,然后在设计时VS 2013中返回时,集合不会消失。

    不使用setter的代码

    private List<Subscription> list = null;
    
    [Category("Behavior"),
     Description("The subscriptions collection"),
     DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
     PersistenceMode(PersistenceMode.InnerDefaultProperty)
    ]
    public List<Subscription> SubscriptionList 
    { 
        get
        {
            if (lists == null)
            {
                lists = new List<Subscription>();
            }
            return lists;
        }
    }
    

    适用于setter的代码

    [Category("Behavior"),
     Description("The subscriptions collection"),            
     DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
     PersistenceMode(PersistenceMode.InnerDefaultProperty)
    ]
    public List<Subscription> SubscriptionList 
    { 
        get
        {
            object s = ViewState["SubscriptionList"];
            if ( s == null)
            {
                ViewState["SubscriptionList"] = new List<Subscription>();
            }
            return (List<Subscription>) ViewState["SubscriptionList"];
        }
        set
        {
            ViewState["SubscriptionList"] = value;
        }
    }