C# ASP.NET:生成以列表为参数的用户控件?

C# ASP.NET:生成以列表为参数的用户控件?,c#,asp.net,C#,Asp.net,如何构建以列表为参数的用户控件,即: <foo:TabMenu runat="server"> <Tabs> <Tab Label="Tab1" PanelId="pnlTab1"/> <Tab Label="Tab2" PanelId="pnlTab2"/> <Tab Label="Tab3" PanelId="pnlTab3"/> </Tabs> </foo:TabMenu> 你需要这样的东西。一切正常,但

如何构建以列表为参数的用户控件,即:

<foo:TabMenu runat="server">
<Tabs>
<Tab Label="Tab1" PanelId="pnlTab1"/>
<Tab Label="Tab2" PanelId="pnlTab2"/>
<Tab Label="Tab3" PanelId="pnlTab3"/>
</Tabs>
</foo:TabMenu>

你需要这样的东西。一切正常,但您必须完成TabCollection类

编辑:对不起,我没有测试代码。反正发现了一些问题就解决了

用户控制

[ParseChildren(true, "Tabs"), PersistChildren(false)]
public partial class TabMenu : UserControl
{

    private TabCollection _tabs;

    [Browsable(false), PersistenceMode(PersistenceMode.InnerProperty), MergableProperty(false)]
    public virtual TabCollection Tabs
    {
        get
        {
            if (this._tabs == null)
                this._tabs = new TabCollection(this);
            return this._tabs;
        }
    }

    protected override ControlCollection CreateControlCollection()
    {
        return new TabMenuControlCollection(this);
    }

}
选项卡

public class Tab : HtmlGenericControl
{

    public string Label
    {
        get { return (string)ViewState["Label"] ?? string.Empty; }
        set { ViewState["Label"] = value; }
    }

}
TabCollection

public class TabCollection : IList, ICollection, IEnumerable
{

    private TabMenu _tabMenu;

    public TabCollection(TabMenu tabMenu)
    {
        if (tabMenu == null)
            throw new ArgumentNullException("tabMenu");

        this._tabMenu = tabMenu;
    }

    public virtual int Add(Tab tab)
    {
        if (tab == null)
            throw new ArgumentNullException("tab");

        this._tabMenu.Controls.Add(tab);

        return this._tabMenu.Controls.Count - 1;
    }

    int IList.Add(object value)
    {
        return this.Add((Tab)value);
    }

    // You have to write other methods and properties as Add.

}
public class TabMenuControlCollection : ControlCollection
{

    public TabMenuControlCollection(TabMenu owner) : base(owner) { }

    public override void Add(Control child)
    {
        if (child == null)
            throw new ArgumentNullException("child");

        if (!(child is TabMenu))
            throw new ArgumentException("The TabMenu control can only have a child of type 'Tab'.");

        base.Add(child);
    }

    public override void AddAt(int index, Control child)
    {
        if (child == null)
            throw new ArgumentNullException("child");

        if (!(child is TabMenu))
            throw new ArgumentException("The TabMenu control can only have a child of type 'Tab'.");

        base.AddAt(index, child);
    }

}
选项卡控件集合

public class TabCollection : IList, ICollection, IEnumerable
{

    private TabMenu _tabMenu;

    public TabCollection(TabMenu tabMenu)
    {
        if (tabMenu == null)
            throw new ArgumentNullException("tabMenu");

        this._tabMenu = tabMenu;
    }

    public virtual int Add(Tab tab)
    {
        if (tab == null)
            throw new ArgumentNullException("tab");

        this._tabMenu.Controls.Add(tab);

        return this._tabMenu.Controls.Count - 1;
    }

    int IList.Add(object value)
    {
        return this.Add((Tab)value);
    }

    // You have to write other methods and properties as Add.

}
public class TabMenuControlCollection : ControlCollection
{

    public TabMenuControlCollection(TabMenu owner) : base(owner) { }

    public override void Add(Control child)
    {
        if (child == null)
            throw new ArgumentNullException("child");

        if (!(child is TabMenu))
            throw new ArgumentException("The TabMenu control can only have a child of type 'Tab'.");

        base.Add(child);
    }

    public override void AddAt(int index, Control child)
    {
        if (child == null)
            throw new ArgumentNullException("child");

        if (!(child is TabMenu))
            throw new ArgumentException("The TabMenu control can only have a child of type 'Tab'.");

        base.AddAt(index, child);
    }

}

这里有一个非常简单的解决方案

Partial Class UserControlStrings_TabMenu
    Inherits System.Web.UI.UserControl

    Private _Tabs As New MyTabsClass(Me)

    <PersistenceMode(PersistenceMode.InnerProperty)>
    Public ReadOnly Property Tabs As MyTabsClass
        Get
            Return _Tabs
        End Get
    End Property
End Class

Public Class MyTabsClass
    Inherits ControlCollection

    Sub New(ByVal owner As Control)
        MyBase.New(owner)
    End Sub

    Public Overrides Sub Add(ByVal child As System.Web.UI.Control)
        MyBase.Add(New MyTab(child))
    End Sub
End Class


Public Class MyTab
    Inherits HtmlGenericControl

    Sub New(ByVal GenericControl As HtmlGenericControl)
        MyBase.New()
        Me.Label = GenericControl.Attributes("Label")
        Me.PanelId = GenericControl.Attributes("Panelid")
    End Sub

    Public Property Label As String = String.Empty
    Public Property PanelId As String = String.Empty

    Public Overrides Function ToString() As String
        Return Me.Label & "-" & Me.PanelId
    End Function
End Class

这是你想要的输出的一个例子吗?还是输入?这就是我希望控件在完成时的使用方式。我不知道如何构建一个以自定义类/结构的列表作为属性的用户控件?很好!我明白了:Foo.Presentation.Controls.TabCollection必须具有“Foo.Presentation.Controls.Tab”类型的项Tab“的类型为”System.Web.UI.HtmlControl.HtmlGenericControl“。你知道为什么visual studio在编辑aspx页面时只知道“TabMenu”和“Tabs”,而不知道“Tab”控件(用于自动完成)?@dcg你的代码与上面的完全相同,或者有什么不同吗?应该是相同的。而且效果很好。但是,当我试图编辑aspx文件时,VisualStudio没有“看到”内部子级和属性。此外,它还突出显示了aspx代码,表示它是无效的模式…:-/这就是我失去“轨迹”的地方。有什么想法吗?