2010-10-01 121 views
2

基于服务器的控件对我来说并不是很好的解决方案,因为我的面板默认情况下应始终包含一个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)引发异常。

+0

可能的重复http://stackoverflow.com/questions/306288/custom-asp-net-container-control? – 2010-10-01 11:59:16

+0

没有我的问题是不同的,至少我不会接受这个问题的答案。 – codymanix 2010-10-01 12:14:53

+0

[我可以用asp.net usercontrols定义我自己的面板控件]可能的重复(http://stackoverflow.com/questions/3829728/can-i-define-my-own-panel-control-with-asp-net -usercontrols) – RPM1984 2010-10-01 12:33:03

回答

0

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

+0

那就是我所做的。 – codymanix 2010-10-01 12:33:59

+0

好了,但模板内的控件永远不会进入设计器页面,因为模板实例在运行时会生成,而实际的控件ID将会不同。你必须使用FindControl来获得对控件的引用。查看Citronas的答案。 – VinayC 2010-10-01 12:46:31

+0

不,它绝对可以使用ParseChildren属性来生成变量。但是,这会为我生成运行时错误(请参阅我的编辑) – codymanix 2010-10-01 14:49:31

0

首先,您需要使用runat =“server”属性。

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

之后,您可以尝试

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

而不是使用的FindControl的我想有可能通过在INamingTemplate集装箱你的用户控件

+0

对不起,在我的示例中忘记了runat标记,我将其包含在我的原始源代码中,但它不起作用。 – codymanix 2010-10-01 12:44:11

+0

使用[ParseChildren(false)]属性可以生成变量。但是这会为我生成运行时错误(请参阅编辑) – codymanix 2010-10-01 14:48:29

0

设计师设置设置一个属性来实现这一行为您不需要创建模板化控件,只需创建一个Composite Web Control。创建面板&复选框,将它们添加到复合控件的控件集合中,调整渲染以便随意显示它,然后使用它运行。

here

*编辑**

这里是你所需要的工作落实。 Make创建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

正如我了解此示例,您不能将子控件添加到Web控件本身中定义的控件以外的复合Web控件中。所以你不能用它作为Container控件。 – codymanix 2010-10-01 12:43:10

+0

您可以将其用作容器控件。在此之后发布代码。 – TheGeekYouNeed 2010-10-01 17:44:52