0

というコレクション プロパティを持つ ASP.Net WebForms 用の単純なカスタム Web コントロールを開発しようとしていますSubscriptions

コントロール プロジェクトを正常にコンパイルし、ツールボックスから aspx ページに問題なく追加できます。

Subscriptions問題は、Visual Studio 2013 のデザイン ビューでコレクション エディターを使用してプロパティのエントリを追加するときです。

複数のサブスクリプションを入力できますが、コレクション エディターの [OK] ボタンをクリックしてからデザイン ビューの [サブスクリプション] プロパティに戻ると、少し前にいくつかのエントリを入力したにもかかわらず、空になっています。

aspx のカスタム コントロールのマークアップ

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

質問: コレクションがデザイン ビューのコントロールのマークアップに表示されない原因となっているコードの誤りは何ですか?

カスタム Web コントロール コード

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

1 に答える 1

0

次の2つの変更を加えることで問題を解決できました。

  1. List のようなコレクションの場合、.Net フレームワークは適切なエディターを自動的に表示するため、コレクションは List タイプであるため、エディターを指定する必要はありません。したがって、この属性は必要ありませんEditor(typeof(SubscriptionCollectionEditor), typeof(UITypeEditor))
  2. のセッターをSubscriptions削除する必要があり、以下のコードのように get のみが存在する必要があります。セッターを使用する場合は、2 番目のコード スニペットのように使用する必要があります。ただし、自動の get および set は、カスタム Web コントロールのコレクション プロパティでは使用しないでください

コレクション プロパティの最終的なコードは次のようになります。これにより、デザインタイム VS 2013 で後でコレクションに戻ったときに、コレクションが消えることはありません。

セッターなしで動作するコード

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

セッターで動作するコード

[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;
    }
}
于 2016-05-21T17:28:26.603 に答える