【问题标题】:ASP Nested Tags in a Custom User Control自定义用户控件中的 ASP 嵌套标签
【发布时间】:2010-09-12 08:51:33
【问题描述】:

我刚刚开始使用 C# 中的自定义用户控件,我想知道是否有任何示例说明如何编写一个接受嵌套标签的控件?

例如,当您创建asp:repeater 时,您可以为itemtemplate 添加嵌套标签。

【问题讨论】:

    标签: c# .net asp.net custom-server-controls


    【解决方案1】:

    前段时间我写了一封blog post 关于这个。简而言之,如果您有一个带有以下标记的控件:

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

    【讨论】:

    • 如果它回答了这个问题,不要认为它是糟糕的形式。这是人们只写博客文章的时候。那是疯狂制作的时候。点击一下。
    • 谢谢!谢谢!谢谢!
    • 哇,这已经在这里站了三年多了,而且一直以来,我都被过于复杂和详尽的“示例”打了耳光,这些示例根本不起作用。谢谢!
    • 链接博客帖子作为答案的问题是网站何时死掉。我正在打字时就是这种情况。因此我看不到答案。
    • @tjmoore 我同意 - 尝试在 The Wayback Machine 上查找它
    【解决方案2】:

    我按照 Rob 的博客文章,做了一个稍微不同的控制。该控件是一个条件控件,实际上就像一个 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 属性设置为布尔值,它决定呈现哪个子句。

    与 Rob 的解决方案的最大区别在于,控件中的子句确实可以包含任意 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);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我最终得到了与Robwayback archive@gudmundur-h 的答案非常相似的东西,但我使用了ITemplate 来摆脱那个烦人的“你不能在 X 标签之间放置内容”在使用中。我不完全确定实际需要什么,所以都在这里以防万一。

      部分/用户控件标记:mycontrol.ascx

      注意重要的位:plcChild1plcChild2

      <!-- 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>
      

      部分/用户控制代码隐藏: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 -- 这么多shows up?
      • PersistChildren -- 所以动态创建的东西不会被重置?
      • PersistenceMode(PersistenceMode.InnerProperty) -- 所以控件是parsed correctly
      • 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>
      

      【讨论】:

        【解决方案4】:

        我猜你正在寻找这样的东西? http://msdn.microsoft.com/en-us/library/aa478964.aspx

        您的标签已被删除或不可见,因此无法真正帮助您。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-01-03
          • 2014-12-26
          • 2019-04-11
          • 2016-08-25
          • 2011-12-15
          • 2019-01-23
          • 2011-03-17
          • 2010-09-08
          相关资源
          最近更新 更多