【问题标题】:Create custom panel control创建自定义面板控件
【发布时间】:2011-04-19 19:47:57
【问题描述】:

基于服务器的控件对我来说不是很好的解决方案,因为默认情况下我的面板应该始终包含一个 asp 复选框,这将允许用户隐藏和显示面板内容。

我将面板创建为模板化用户控件,但现在我遇到无法在其中声明变量的问题。

[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 中,它们通常会这样做:

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

因此foo不是设计者创建的控制变量,所以我无权访问它。

如何创建自己的允许在其中声明控件的面板?

编辑: 我现在尝试使用[ParseChildren(false)]。包含变量的变量现在在表单的设计器代码中生成。现在的问题是messageTemplate.InstantiateIn(container) 抛出了异常。

【问题讨论】:

标签: c# asp.net user-controls panel


【解决方案1】:

您还没有给出控件的代码。通常,它需要实现 INamingContainer 并且应该具有 ITemplate 类型的属性以接受模板。 检查MSDN 如何开发一个。这是来自 MSDN 的sample code。还要检查此article 以获取数据绑定模板控件。

【讨论】:

  • 好的,但是模板中的控件永远不会进入设计器页面,因为模板实例是在运行时生成的,实际控件 ID 会有所不同。您必须使用 FindControl 来获取对控件的引用。请参阅 Citronas 的回答。
  • 不,绝对可以使用 ParseChildren 属性生成变量。但这会为我生成运行时错误(请参阅我的编辑)
【解决方案2】:

首先,你需要使用 runat="server" 属性。

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

之后你可以试试

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

我想可以通过在用户控件的 INamingTemplate 容器的设计器设置上设置属性来实现此行为,而不是使用 FindControl

【讨论】:

  • 对不起,忘记了我的例子中的 runat 标签,我包含在我的原始源中并且它不起作用。
  • 绝对可以使用 [ParseChildren(false)] 属性生成变量。但这会为我生成运行时错误(请参阅编辑)
【解决方案3】:

您不需要创建模板化控件,只需创建一个复合 Web 控件。创建一个 Panel & Checkbox,将它们添加到复合控件的控件集合中,调整渲染以根据需要显示,然后运行。

here

* 编辑 **

这是您需要的工作实施。为 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);
        }
    }
}

默认.aspx

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

默认.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);
 }

【讨论】:

  • 据我了解此示例,除了在 Web 控件本身中定义的控件之外,您不能将子控件添加到复合 Web 控件中。所以你不能把它当作一个Container控件来使用。
  • 您可以将其用作容器控件。在此之后发布代码。
猜你喜欢
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-06
  • 2012-05-25
相关资源
最近更新 更多