Вложенные Теги ASP в пользовательском элементе управления
Я только начинаю работать с пользовательскими элементами управления в c#, и мне интересно, есть ли какие-либо примеры того, как написать тот, который принимает вложенные теги. Например, при создании " asp: repeater "можно добавить вложенный тег для"itemtemplate".
Любая помощь прилагается!
Ура
4 ответа:
Я написал сообщение в блоге об этом некоторое время назад. Короче говоря, если у вас был элемент управления со следующей разметкой:
<Abc:CustomControlUno runat="server" ID="Control1"> <Children> <Abc:Control1Child IntegerProperty="1" /> </Children> </Abc:CustomControlUno>
Вам нужно, чтобы код в элементе управления был примерно таким:
[ParseChildren(true)] [PersistChildren(true)] [ToolboxData("<{0}:CustomControlUno runat=server></{0}:CustomControlUno>")] public class CustomControlUno : WebControl, INamingContainer { private Control1ChildrenCollection _children; [PersistenceMode(PersistenceMode.InnerProperty)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public Control1ChildrenCollection Children { get { if (_children == null) { _children = new Control1ChildrenCollection(); } return _children; } } } public class Control1ChildrenCollection : List<Control1Child> { } public class Control1Child { public int IntegerProperty { get; set; } }
Я проследил за постом Роба в блоге и сделал немного другой контроль. Элемент управления является условным, на самом деле так же, как предложение if:
<wc:PriceInfo runat="server" ID="PriceInfo"> <IfDiscount> You don't have a discount. </IfDiscount> <IfNotDiscount> Lucky you, <b>you have a discount!</b> </IfNotDiscount> </wc:PriceInfo>
В коде я затем устанавливаю свойство
HasDiscount
элемента управления в логическое значение, которое решает, какое предложение выводится.Большое отличие от решения Роба состоит в том, что предложения внутри элемента управления действительно могут содержать произвольный HTML/ASPX код.
А вот код для управления:
using System.ComponentModel; using System.Web.UI; using System.Web.UI.WebControls; namespace WebUtilities { [ToolboxData("<{0}:PriceInfo runat=server></{0}:PriceInfo>")] public class PriceInfo : WebControl, INamingContainer { private readonly Control ifDiscountControl = new Control(); private readonly Control ifNotDiscountControl = new Control(); public bool HasDiscount { get; set; } [PersistenceMode(PersistenceMode.InnerProperty)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public Control IfDiscount { get { return ifDiscountControl; } } [PersistenceMode(PersistenceMode.InnerProperty)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public Control IfNotDiscount { get { return ifNotDiscountControl; } } public override void RenderControl(HtmlTextWriter writer) { if (HasDiscount) ifDiscountControl.RenderControl(writer); else ifNotDiscountControl.RenderControl(writer); } } }
Я думаю, вы ищете что-то вроде этого? http://msdn.microsoft.com/en-us/library/aa478964.aspx
Ваши теги были удалены или невидимы, так что не могут реально помочь вам там.
Я закончил с чем-то очень похожим на ответ Rob (в архиве wayback) @gudmundur-h , но я использовал
ITemplate
, Чтобы избавиться от этого раздражающего "вы не можете размещать контент между тегами X" в использовании. Я не совсем уверен, что на самом деле требуется или нет, так что все здесь на всякий случай.Разметка частичного/пользовательского управления:
mycontrol.ascx
Обратите внимание на важные биты:
plcChild1
иplcChild2
.<!-- markup, controls, etc --> <div class="shell"> <!-- etc --> <!-- optional content with default, will map to `ChildContentOne` --> <asp:PlaceHolder ID="plcChild1" runat="server"> Some default content in the first child. Will show this unless overwritten. Include HTML, controls, whatever. </asp:PlaceHolder> <!-- etc --> <!-- optional content, no default, will map to `ChildContentTwo` --> <asp:PlaceHolder ID="plcChild2" runat="server"></asp:PlaceHolder> </div>
Частичное / пользовательское управление codebehind:
mycontrol.ascx.cs
[ParseChildren(true), PersistChildren(true)] [ToolboxData(false /* don't care about drag-n-drop */)] public partial class MyControlWithNestedContent: System.Web.UI.UserControl, INamingContainer { // expose properties as attributes, etc /// <summary> /// "attach" template to child controls /// </summary> /// <param name="template">the exposed markup "property"</param> /// <param name="control">the actual rendered control</param> protected virtual void attachContent(ITemplate template, Control control) { if(null != template) template.InstantiateIn(control); } [PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public virtual ITemplate ChildContentOne { get; set; } [PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public virtual ITemplate ChildContentTwo { get; set; } protected override void CreateChildControls() { // clear stuff, other setup, etc // needed? base.CreateChildControls(); this.EnsureChildControls(); // cuz...we want them? // using the templates, set up the appropriate child controls attachContent(this.ChildContentOne, this.plcChild1); attachContent(this.ChildContentTwo, this.plcChild2); } }
Важные биты (?):
ParseChildren
- значит, все появляется ?PersistChildren
- значит, динамически создаваемый материал не сбрасывается?PersistenceMode(PersistenceMode.InnerProperty)
-- таким образом, элементы управления разбираются правильноDesignerSerializationVisibility(DesignerSerializationVisibility.Content)
- то же самое?Использование контроля
<%@ Register Src="~/App_Controls/MyStuff/mycontrol.ascx" TagPrefix="me" TagName="MyNestedControl" %> <me:MyNestedControl SomeProperty="foo" SomethingElse="bar" runat="server" ID="meWhatever"> <%-- omit `ChildContentOne` to use default --%> <ChildContentTwo>Stuff at the bottom! (not empty anymore)</ChildContentTwo> </me:MyNestedControl>