Как сделать контроль с детьми, не объявляя тег шаблона? - PullRequest
6 голосов
/ 13 июля 2010

Я хочу создать элемент управления как Panel.

Я хочу, чтобы мой элемент управления принимал некоторые элементы управления как дочерние элементы без ввода имени шаблона, как Panel, как показано здесь:

<asp:Panel runat="server">
    My content
    <div>Content</div>
</asp:Panel>

У меня есть элементы управления с содержимым внутри, не говоря, что такое ITemplate.

Я в основном хочу преобразовать это

<my:MyControl runat="server">
    <ContentTemplate>
        My content
        <div>Content</div>
    </ContentTemplate>
</my:MyControl>

В это

<my:MyControl runat="server">
    My content
    <div>Content</div>
</my:MyControl>

Вот что у меня есть:

public class MyControl : CompositeControl
{
    [TemplateInstance(TemplateInstance.Single)]
    public ITemplate Content { get; set; }

    protected override void CreateChildControls()
    {
        base.CreateChildControls();

        Content.InstantiateIn(this);
    }
}

Вышеуказанное работает с тегами <Content></Content> внутри элемента управления, но без него не работает. А атрибут вообще ничего не делает (наверное). Чего не хватает?

Как мне этого добиться? Есть намеки? Почему Panel поддерживает это?

Ответы [ 6 ]

7 голосов
/ 12 октября 2010

Я пишу это из памяти, но я считаю, что ответ прост, как украсить ваш класс управления с атрибутами ParseChildrenAttribute и PersistChildrenAttribute и вам не нужно работать с шаблонами как вы предлагаете.

ParseChildrenAttribute.ChildrenAsProperties указывает, должен ли анализатор обрабатывать вложенное содержимое тега элемента управления как свойства. Если установить значение false, парсер не будет пытаться сопоставить теги с именами свойств.

PersistChildrenAttribute сообщит анализатору обрабатывать вложенное содержимое как элементы управления, а проанализированные элементы управления будут добавлены как дочерние элементы управления в пользовательский элемент управления панели.

Код вашего элемента управления будет выглядеть примерно так:

[ParseChildren(false)]
[PersistChildren(true)]
public class MyControl : CompositeControl 
{
    public override void RenderBeginTag(HtmlTextWriter writer)
    {
        base.RenderBeginTag(writer); // TODO: Do something else here if needed
    }     

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        base.RenderEndTag(writer); // TODO: Do something else here if needed
    }
} 

Для справки вы можете запустить .NET Reflector и посмотреть на реализацию элемента управления Panel.

4 голосов
/ 13 июля 2010

Бруно, вы, вероятно, ищете это .А также аналогичный ответ здесь .

2 голосов
/ 13 июля 2010

Привет, Бруно, ответ не имеет ничего общего с пользовательским контролем с точки зрения того, как ты хочешь вкладывать элементы управления.

Это на самом деле связано с шаблонами и шаблонами. Вот так серверные элементы управления могут иметь вложенные элементы управления.

Это обычно в элементах управления с привязкой к данным.

Ответ, к сожалению, не тривиален, но вы можете найти полное руководство здесь

UPDATE

Хм .... Я думаю, где просто все усложняется. Что мешает вам создать собственный элемент управления, вложить в него элементы управления, а затем получить к ним доступ через свойство ControlCollection родительского элемента управления?

1 голос
/ 12 октября 2010

Первые две строки заставляют его работать:

[ParseChildren(false)]
[PersistChildren(true)]
[ToolboxData("<{0}:MyPanel runat=server>Panel</{0}:MyPanel>")]
public class MyPanel : WebControl
{
}

HTML:

<%@ Register Assembly="WebApplication3" Namespace="WebApplication3" TagPrefix="cc1" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <cc1:MyPanel ID="MyPanel1" runat="server">
        <h2>
            Welcome to ASP.NET!
        </h2>
        <p>
            To learn more about ASP.NET visit <a href="http://www.asp.net" title="ASP.NET Website">
                www.asp.net</a>.
        </p>
        <p>
            You can also find <a href="http://go.microsoft.com/fwlink/?LinkID=152368&amp;clcid=0x409"
                title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
        </p>
    </cc1:MyPanel>
</asp:Content>
1 голос
/ 24 августа 2010

В зависимости от того, что вам нужно с ним сделать, вы можете просто создать подкласс элемента управления asp.net Panel.

Я создал что-то вроде следующего для инкапсуляции общего HTML, который я хотел на каждом из моихсобственные панели.(PanelWidth - это перечисление, определяющее некоторые стандартные размеры.)

public class StyledPanel : System.Web.UI.WebControls.Panel
{
    public PanelWidth PanelWidth { get; set; }

    public override void RenderBeginTag(HtmlTextWriter writer) {            
        string containerClass = string.Format("panel-container-{0}", (int)PanelWidth);
        writer.WriteLine("<div class=\"" + containerClass + "\"" + ">");
    }

    public override void RenderEndTag(HtmlTextWriter writer) {
        writer.WriteLine("</div>");
    }
}

Назовите это, например,

<uc:StyledPanel PanelWidth="Full" runat="server">
  <div>Stuff</div>
</uc:StyledPanel>
0 голосов
/ 13 июля 2010

Создайте пользовательский элемент управления и затем используйте его для дальнейшего расширения дочерних элементов управления.

http://www.akadia.com/services/dotnet_user_controls.html

    using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
namespace Akadia
{
    namespace SubmitButton
    {
        // User Control which contain a text box for your
        // name and a button that will fire an event.
        public class SubmitButtonControl : System.Windows.Forms.UserControl
        {
            private System.Windows.Forms.TextBox txtName;
            private System.Windows.Forms.Label lblName;
            private System.Windows.Forms.Button btnSubmit;
            private System.ComponentModel.Container components = null;
            // Declare delegate for submit button clicked.
            //
            // Most action events (like the Click event) in Windows Forms
            // use the EventHandler delegate and the EventArgs arguments.
            // We will define our own delegate that does not specify parameters.
            // Mostly, we really don't care what the conditions of the
            // click event for the Submit button were, we just care that
            // the Submit button was clicked.
            public delegate void SubmitClickedHandler();
            // Constructor           public SubmitButtonControl()
            {
                // Create visual controls
                InitializeComponent();
            }
            // Clean up any resources being used.
            protected override void Dispose( bool disposing )
            {
                if( disposing )
                {
                    if( components != null )
                        components.Dispose();
                }
                base.Dispose( disposing );
            }
            .....
            .....
            // Declare the event, which is associated with our
            // delegate SubmitClickedHandler(). Add some attributes
            // for the Visual C# control property.
            [Category("Action")]
            [Description("Fires when the Submit button is clicked.")]
            public event SubmitClickedHandler SubmitClicked;
            // Add a protected method called OnSubmitClicked().
            // You may use this in child classes instead of adding
            // event handlers.
            protected virtual void OnSubmitClicked()
            {
                // If an event has no subscribers registerd, it will
                // evaluate to null. The test checks that the value is not
                // null, ensuring that there are subsribers before
                // calling the event itself.
                if (SubmitClicked != null)
                {
                    SubmitClicked();  // Notify Subscribers
                }
            }
            // Handler for Submit Button. Do some validation before
            // calling the event.
            private void btnSubmit_Click(object sender, System.EventArgs e)
            {
                if (txtName.Text.Length == 0)
                {
                    MessageBox.Show("Please enter your name.");
                }
                else
                {
                    OnSubmitClicked();
                }
            }
            // Read / Write Property for the User Name. This Property
            // will be visible in the containing application.
            [Category("Appearance")]
            [Description("Gets or sets the name in the text box")]
            public string UserName
            {
                get { return txtName.Text; }
                set { txtName.Text = value; }
            }
        }
    }
}
...