Создать настраиваемую панель управления - PullRequest
2 голосов
/ 01 октября 2010

Серверный элемент управления не является хорошим решением для меня, поскольку моя панель по умолчанию всегда должна содержать флажок asp , который позволит пользователю скрывать и отображать содержимое панелей.

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

[ParseChildren(true)]
public partial class MyPanel: System.Web.UI.UserControl
{

    private ITemplate messageTemplate = null;

    [TemplateContainer(typeof(MessageContainer))]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public ITemplate Content
    {
        get
        {
            return messageTemplate;
        }
        set
        {
            messageTemplate = value;
        }
    }

    void Page_Init()
    {
        MessageContainer container = new MessageContainer();
        messageTemplate.InstantiateIn(container);
        PlaceHolder1.Controls.Add(container);
    }

    [ParseChildren(true)]
    public class MessageContainer : Control, INamingContainer
    {

        internal MessageContainer()
        {
        }

    }
}

Если я сделаю следующее в MyPage.aspx, тогда определениями управления будут , а не , вставленные в MyPage.aspx.designer.cs a, которые они обычно делают:

<my:MyPanel>
  <Content>
    <asp:TextBox id = "foo" runat="server" />
  </Content>
</my:MyPanel>

Поэтому foo не создается дизайнером как переменная управления, поэтому у меня нет к ней доступа.

Как я могу создать свою собственную панель, которая позволяет декларировать элементы управления в ней?

EDIT: Я сейчас попробовал с [ParseChildren(false)]. Переменные для содержащихся переменных теперь генерируются в коде конструктора формы. Проблема в том, что messageTemplate.InstantiateIn(container) выдает исключение.

Ответы [ 3 ]

0 голосов
/ 01 октября 2010

Прежде всего, вам нужно использовать атрибут runat = "server".

<asp:TextBox id = "foo"  runat="server"/>

После этого вы можете попробовать

var textbox = this.MyCustomPanel.FindControl("foo") as TextBox;

Вместо использования FindControl, я думаю, можно добиться такого поведения, установив атрибут в настройках конструктора контейнера INamingTemplate вашего Usercontrol

0 голосов
/ 01 октября 2010

Вам не нужно создавать шаблонный элемент управления, просто создайте Composite Web Control. Создайте панель и флажок, добавьте их в коллекцию элементов управления составного элемента управления, настройте рендеринг так, чтобы он отображался по вашему желанию, и запустите его.

смотрите здесь

* РЕДАКТИРОВАТЬ **

Вот рабочая реализация того, что вам нужно. Сделайте, чтобы создать ссылку на Web.dll.

CustomPanel.cs

using System;
using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;


namespace Web
{
    [    AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal), 
         AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
         ToolboxData("<{0}:CustomPanel runat=\"server\"> </{0}:CustomPanel>"),
]

    public class CustomPanel : CompositeControl
{
        private Panel panelContainer;
        private CheckBox chkHideContent;
        private Panel panelInnerContainer;

        [Bindable(true),
        Category("Appearance"),
        DefaultValue(""),
        Description("The text to display with the checkbox.")]
        public string CheckBoxText
        {
            get
            {
                EnsureChildControls();
                return chkHideContent.Text;
            }
            set
            {
                EnsureChildControls();
                chkHideContent.Text = value;
            }
        }

        [Bindable(true)]
        [Category("Data")]
        [DefaultValue("")]
        [Localizable(true)]
        public bool IsCheckBoxChecked
        {
            get
            {
                return chkHideContent.Checked;
            }
        }

        [Bindable(true)]
        [Category("Data")]
        [DefaultValue("")]
        [Localizable(true)]
        public bool HideInnerPanel
        {
            set
            {
                EnsureChildControls();
                panelInnerContainer.Visible = value;
            }
        }

        [Bindable(true)]
        [Category("Data")]
        [DefaultValue("")]
        [Localizable(true)]
        public ControlCollection InnerPanelControls
        {
            get
            {
                EnsureChildControls();
                return panelInnerContainer.Controls;
            }
        }

        protected virtual void OnCheckboxChanged(EventArgs e)
        {
            if (chkHideContent.Checked)
            {
                panelInnerContainer.Visible = false;
            }
            else
            {
                panelInnerContainer.Visible = true;
            }
        }

        private void _checkbox_checkChanged(object sender, EventArgs e)
        {
            OnCheckboxChanged(EventArgs.Empty);
        }

        protected override void RecreateChildControls()
        {
            EnsureChildControls();
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();

            panelContainer = new Panel();
            panelContainer.ID = "panelContainer";

            chkHideContent = new CheckBox();
            chkHideContent.ID = "chkHideContent";
            chkHideContent.CheckedChanged += new EventHandler(_checkbox_checkChanged);
            chkHideContent.AutoPostBack = true;

            panelInnerContainer = new Panel();
            panelInnerContainer.ID = "panelInnerContainer";

            this.Controls.Add(panelContainer);
            this.Controls.Add(chkHideContent);
            this.Controls.Add(panelInnerContainer);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            panelContainer.RenderBeginTag(writer);
            chkHideContent.RenderControl(writer);
            panelInnerContainer.RenderControl(writer);
            panelContainer.RenderEndTag(writer);
        }
    }
}

Default.aspx

<%@ Register assembly="Web" namespace="Web" tagprefix="cc1" %>
<cc1:CustomPanel ID="CustomPanel1" runat="server" />

Default.aspx.cs

 protected void Page_Load(object sender, EventArgs e)
 {
        Label lbl = new Label();
        lbl.Text = "IT WORKS!";

        CustomPanel1.CheckBoxText = "Hide my innards!";
        CustomPanel1.InnerPanelControls.Add(lbl);
 }
0 голосов
/ 01 октября 2010

Вы не дали код для элемента управления. В целом, он должен реализовывать INamingContainer и иметь свойства типа ITemplate для приема шаблонов. Проверьте MSDN о том, как его разработать. А вот пример кода из MSDN. Также проверьте эту статью для шаблонного элемента управления с привязкой к данным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...