2010-10-01 125 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