2009-05-07 9 views
1

サーバーコントロール、コントロールベースクラス、およびそれらのクラスの使用方法の作成に関する話題を紹介してくれることを願っています。カスタムサーバーコントロール - 基底クラスと使用法

ここに私が達成したいものの例があります。

<div id="MyPanel" class="panel scroll-contents"> 
    <div class="panel-header"> 
    <div class="panel-header-l"></div> 
    <div class="panel-header-c"> 
     <div class="panel-header-wrapper">My Panel Header</div> 
    </div> 
    <div class="panel-header-r"></div> 
    </div> 
    <div class="panel-toolbars"> 
    // HTML of Toolbar control 
    </div> 
    <div class="panel-body"> 
    <div class="panel-body-t"> 
     <div class="panel-body-tl"></div> 
     <div class="panel-body-tc"></div> 
     <div class="panel-body-tr"></div> 
    </div> 
    <div class="panel-body-m"> 
     <div class="panel-body-ml"></div> 
     <div class="panel-body-mc"> 
     <div class="panel-body-wrapper"> 
      // Contents 
     </div> 
     </div> 
     <div class="panel-body-mr"></div> 
    </div> 
    <div class="panel-body-b"> 
     <div class="panel-body-bl"></div> 
     <div class="panel-body-bc"></div> 
     <div class="panel-body-br"></div> 
    </div> 
    </div> 
    <div class="panel-footer"> 
    <div class="panel-footer-l"></div> 
    <div class="panel-footer-c"> 
     <div class="panel-footer-wrapper"> 
     // Footer contents 
     </div> 
    </div> 
    <div class="panel-footer-r"></div> 
    </div> 
</div> 

は、開発者は、任意のを省略することができるはずです。

<acme:Panel ID="MyPanel" runtat="server" Scrolling="true"> 
    <Header>My Panel Header</Header> 
    <Toolbars> 
    <acme:Toolbar ID="Toolbar1" runat="server"/> 
    <acme:Toolbar ID="Toolbar2" runat="server"/> 
    </Toolbars> 
    <Contents> 
    <%-- Some Content for the Contents section --%> 
    </Contents> 
    <Footer> 
    <%-- Some Content for the Footer section --%> 
    </Footer> 
</acme:Panel> 

それは、次のHTMLをレンダリングする必要があります:私は1つはそうのようなASPXマークアップでインスタンス化できるカスタムパネルコントロールを作成したいです目次セクション以外のセクション。省略されたセクションのHTMLはレンダリングされません。プラスユーザーは、ページの背後にあるコードにPanelコントロールを追加し、そのように、Panelコントロールのさまざまなセクションに追加のコントロールを追加/インスタンス化することができるはずです。

ACME.Panel MyPanel = new ACME.Panel(); 
MyPlaceHolder.Controls.Add(MyPanel); 

MyPanel.Header = "My Panel Header"; 

MyPanel.Toolbars.Controls.Add(new ACME.Toolbar()); 

MyPanel.Footer.Controls.Add(new Literal()); 

MyPanel.Contents.Controls.Add(new GridView()); 

私は次の記事を読みました:カスタムクラスのASP.NETサーバーコントロールの作成(基本クラスは何ですか?)

開発者が自分のコントロールのスタイリングを変更しないようにしたいので、System.Web.UI.Controlの基底クラスで十分ですしかし、私はまた、INamingContainerインターフェイスを適用する必要があります。したがって、私のコントロールはそうのようになります。

using System.Web; 
using System.Web.UI; 
using System.Web.UI.Design; 
using System.Web.UI.HtmlControls; 
using System.Web.UI.WebControls; 
using System.ComponentModel; 
using System.ComponentModel.Design; 
using System.Security.Permissions; 
namespace ACME 
{ 
    [ToolboxData("&lt;{0}:Panel runat=server></{0}:Panel >")] 
    [ParseChildren(true)] 
    public class Panel : Control, INamingContainer 
    { 
     private string _header; 
     private ITemplate _toolbars; 
     private ITemplate _contents; 
     private ITemplate _footerContents; 
     public DialogBox() 
     { 
     } 
     [Browsable(false), 
     PersistenceMode(PersistenceMode.InnerProperty)] 
     public virtual ITemplate Toolbars 
     { 
      get { return _toolbars; } 
      set { _toolbars = value; } 
     } 
     [Browsable(false), 
     PersistenceMode(PersistenceMode.InnerProperty)] 
     public virtual ITemplate Contents 
     { 
      get { return _contents; } 
      set { _contents= value; } 
     } 
     [Browsable(false), 
     PersistenceMode(PersistenceMode.InnerProperty)] 
     public virtual ITemplate Footer 
     { 
      get { return _footerContents; } 
      set { _footerContents = value; } 
     } 
    } 
} 

を私は多くのチュートリアルを読みましたが、彼らは私の意図した実装を覆ったり、特定のアプローチが取られた理由を説明していないのいずれか。彼らはまた私を混乱させて、JavaScriptを使って必要なHTMLを動的にレンダリングしました。そこにControl Guruがいる場合は、この作業にどのように取り組んだのか説明してください。

答えて

2

これは長い1、従うべき多くのコードになるだろう:あなたが出てレンダリングしたい共通の要素がたくさんあるので

、私が生成するいくつかの一般的なメソッドを定義しBaseControlで開始しましたあなたが終わったすべての部署これはSystem.Web.UI.Controlからドキュメントの状態として継承されます。

これは、カスタムASP.NETサーバーコントロールを開発するときに派生するプライマリクラスです。 コントロールには、ユーザーインターフェイス(UI)固有の機能がありません。 UIを持たないコントロールを作成する場合、または独自のUIをレンダリングする他のコントロールを組み合わせる場合は、コントロールから派生します。

だから、基本制御は次のようになります。

/// <summary> 
/// Provides some common methods. 
/// </summary> 
public class BaseControl: Control 
{ 
    protected Control[] TempControls; 

    /// <summary> 
    /// Clears the child controls explicitly, and stores them locally. 
    /// </summary> 
    protected void ClearControls() 
    { 
     if (HasControls()) 
     { 
      TempControls = new Control[Controls.Count]; 
      Controls.CopyTo(TempControls, 0); 
     } 

     Controls.Clear(); 
    } 
    /// <summary> 
    /// Creates a new panel (HTML div) with the requested CSS 
    /// and containing any controls passed in. 
    /// </summary> 
    /// <param name="cssClass">The CSS class to be applied</param> 
    /// <param name="controls">Any controls that should be added to the panel</param> 
    protected Panel NewPanel(string cssClass, params Control[] controls) 
    { 
     // Create a new Panel, assign the CSS class. 
     var panel = new Panel { CssClass = cssClass }; 

     // Loop through the controls adding them to the panel. 
     foreach (var control in controls) 
     { 
      panel.Controls.Add(control); 
     } 

     return panel; 
    } 

    /// <summary> 
    /// Creates a new row of panels (HTML div), based on the CSS class prefix. 
    /// The center panel holds the controls passed in. 
    /// </summary> 
    /// <param name="cssClassPrefix"></param> 
    /// <param name="controls"></param> 
    protected Panel NewRow(string cssClassPrefix, params Control[] controls) 
    { 
     // Expaned for clarity, but could all be passed in on one call. 
     var row = NewPanel(cssClassPrefix); 
     row.Controls.Add(NewPanel(cssClassPrefix + "-l")); 
     row.Controls.Add(NewPanel(cssClassPrefix + "-c", controls)); 
     row.Controls.Add(NewPanel(cssClassPrefix + "-r")); 

     return row; 
    } 
} 

あなたが、私はここ2を作成した、あなたのテンプレートのそれぞれを処理するいくつかのコントロールを作成する必要があります。

まずは、単一の行を生成する制御 - ヘッダとフッタの両方で使用される:

public class AcmeSimple : BaseControl, INamingContainer 
{ 
    private string m_CssPrefix; 

    public AcmeSimple(string cssPrefix) 
    { 
     m_CssPrefix = cssPrefix; 
    } 

    protected override void CreateChildControls() 
    { 

     ClearControls(); 

     Panel wrapper = NewPanel(m_CssPrefix + "-wrapper", TempControls); 

     Panel simple = NewRow(m_CssPrefix, wrapper); 

     Controls.Add(simple); 

     base.CreateChildControls(); 
    } 
} 

が制御を保持するために新しいパネルを作成し、その後にdiv要素の新しい行を作成ラッパーを保持します。

そして、ヘッダと同じ原理で動作しますもう少し複雑な内容の制御、:

public class AcmeContents: BaseControl, INamingContainer 
{ 
    protected override void CreateChildControls() 
    { 
     ClearControls(); 

     Panel wrapper = NewPanel("panel-body-wrapper", TempControls); 

     Panel contents = NewPanel("panel-body"); 
     contents.Controls.Add(NewRow("panel-body-t")); 
     contents.Controls.Add(NewRow("panel-body-m", wrapper)); 
     contents.Controls.Add(NewRow("panel-body-b")); 

     Controls.Add(contents); 

     base.CreateChildControls(); 
    } 
} 

ので、コントロールが含まれている中央の一つは、わずか3行を作成し、この1、。

最後に、あなたがページに配置、実際の制御:

[ParseChildren(true)] 
[ToolboxData("<{0}:AcmeControl runat=server></{0}:AcmeControl>")] 
public class AcmeControl: BaseControl, INamingContainer 
{ 

    public bool Scrolling { get; set; } 

    [TemplateContainer(typeof(AcmeSimple))] 
    public ITemplate Header { get; set; } 
    [TemplateContainer(typeof(AcmeContents))] 
    public ITemplate Contents { get; set; } 
    [TemplateContainer(typeof(AcmeSimple))] 
    public ITemplate Footer { get; set; } 

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

     string cssClass = "panel"; 

     if (Scrolling) 
     { 
      cssClass += " scrollContents"; 
     } 

     Panel panel = NewPanel(cssClass); 
     panel.ID = ID; 
     Controls.Add(panel); 

     if (Header != null) 
     { 
      var header = new AcmeHeader("panel-header"); 
      Header.InstantiateIn(header); 
      panel.Controls.Add(header); 
     } 

     if (Contents != null) 
     { 
      var contents = new AcmeContents(); 
      Contents.InstantiateIn(contents); 
      panel.Controls.Add(contents); 
     } 
     else 
     { 
      // Possibly a little harsh, as it's a runtime exception. 
      throw new ArgumentNullException("Contents", "You must supply a contents template."); 
     } 

     if (Footer != null) 
     { 
      var footer = new AcmeSimple("panel-footer"); 
      Footer.InstantiateIn(footer); 
      panel.Controls.Add(footer); 
     } 
    } 
} 

だから我々はあなたが望んでいたスクロール可能なプロパティと一緒に、我々はコントロールのプロパティとしてサポートするテンプレートを定義します。次に、CreateChildControlsでは、Beginnerで作成したコントロールとBaseControlのメソッドを使用して、コントロールの本体を構築します。

これは次のようにページに行く:

<cc1:AcmeControl ID="AcmeControl1" runat="server"> 
    <Header> 
    <b>Here's a header</b> 
    </Header> 
    <Contents> 
    <i>Here's some controls in the content.</i> 
    </Contents> 
</cc1:AcmeControl> 

そして、このようにアウトレンダリング:

<div id="AcmeControl1_AcmeControl1" class="panel"> 
    <div class="panel-header"> 
     <div class="panel-header-l"> 
     </div> 
     <div class="panel-header-c"> 
      <div class="panel-header-wrapper"> 
       <b>Here's a header</b> 
      </div> 
     </div> 
     <div class="panel-header-r"> 
     </div> 
    </div> 
    <div class="panel-body"> 
     <div class="panel-body-t"> 
      <div class="panel-body-t-l"> 
      </div> 
      <div class="panel-body-t-c"> 
      </div> 
      <div class="panel-body-t-r"> 
      </div> 
     </div> 
     <div class="panel-body-m"> 
      <div class="panel-body-m-l"> 
      </div> 
      <div class="panel-body-m-c"> 
       <div class="panel-body-wrapper"> 
        <i>Here's some controls in the content.</i> 
       </div> 
      </div> 
      <div class="panel-body-m-r"> 
      </div> 
     </div> 
     <div class="panel-body-b"> 
      <div class="panel-body-b-l"> 
      </div> 
      <div class="panel-body-b-c"> 
      </div> 
      <div class="panel-body-b-r"> 
      </div> 
     </div> 
    </div> 
</div> 

だから、唯一の違いは、コンテンツのスタイルではなく、TLよりTLであるということです。

AcmeControl1.Footer.Controls.Add([...]); 

ウォン」:あなたが書き込もうとしていることに気づくでしょう - しかし(これはあなたのための大きな問題である可能性があり)、テンプレートコントロールは、実際にコードビハインドから充填されるように設計されていません

tコンパイルします。

AcmeControl1.Footer = Page.LoadTemplate([...]) 

ASCXファイルへのパスを渡す:あなたはしかし、何ができるか

は呼び出しです。また、テンプレートコントロールを作成する上で読ん

を見つけることができます:

私はそれは長いだろうと述べました。

関連する問題