22

この質問は以前に尋ねられました

しかし、もう一度尋ねても問題ありません。

UserControlASP.netにテンプレートを追加するにはどうすればよいですか?

これまでうまくいかなかったこと

  1. 新しいUserControl5から始めます。これを と呼びますContoso:

    public partial class Contoso: System.Web.UI.UserControl
    {
    }
    

    これにより、新しいコントロールを使用できるようになります: 1

    <Contoso>
        Stuff in here
    <Contoso>
    
  2. タイプのパブリックContentTemplateプロパティを作成しITemplateます。

    public partial class Contoso: System.Web.UI.UserControl
    {
       public ITemplate ContentTemplate { get; set; }
    }
    

    不確定な数の属性をプロパティに追加しContentTemplateます: 2

    //[ParseChildren(true)]
    [ParseChildren(true, "ContentTemplate")]
    //[ParseChildren(false)]
    public partial class Contoso: System.Web.UI.UserControl
    {
       [TemplateContainer(typeof(ContentContainer))]
       [TemplateInstance(TemplateInstance.Single)]
       [PersistenceMode(PersistenceMode.InnerProperty)]   
       //[PersistenceMode(PersistenceMode.InnerDefaultProperty)] 
       [Browsable(true)]
       //[Browsable(false)]
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
       //[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
       public ITemplate ContentTemplate { get; set; }
    }
    

    <ContentTemplate>これにより、aspx ファイルのコントロールに次のように追加できます: 1

    <Contoso>
       <ContentTemplate>
           Stuff in here
       </ContentTemplate>
    </Contoso>
    
  3. 次に、どこかに追加して、実際に使用する必要があります。ContentTemplateこれを行うには、UserControl の内部div要素の 1 つに追加します。

    .aspx最初は空だったファイルから始めます。

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
    

    div私たちのものを保持する親を追加しますContentTemplate:

    <%@ Control Language="C#" AutoEventWireup="true" CodeFile="Contoso.aspx.cs" Inherits="Contoso" %>
    <div id="ContentDiv" runat="server"></div>
    

    次に、コントロールのInitContentTemplate中にその親に内容を詰め込みます。div

    public partial class Contoso: System.Web.UI.UserControl
    {
       protected override void OnInit(EventArgs e)
       {
          base.OnInit(e);
    
          //If there's content, then put it into our ContentDiv div
          if (this.ContentTemplate != null)
             this.ContentTemplate.InstantiateIn(ContentDiv);
       }
    
       [PersistenceModeAttribute(PersistenceMode.InnerProperty)]    
       [TemplateInstanceAttribute(TemplateInstance.Single)]
       [Browsable(true)]
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
       public ITemplate ContentTemplate { get; set; }
    }
    
  4. 編集:クラスが実装することを示しますINamingContainer

    public partial class Contoso: System.Web.UI.UserControl: INamingContainer
    {
       protected override void OnInit(EventArgs e)
       {
          base.OnInit(e);
    
          //If there's content, then put it into our ContentDiv div
          if (this.ContentTemplate != null)
             this.ContentTemplate.InstantiateIn(ContentDiv);
       }
    
       [PersistenceModeAttribute(PersistenceMode.InnerProperty)]    
       [TemplateInstanceAttribute(TemplateInstance.Single)]
       [Browsable(true)]
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
       public ITemplate ContentTemplate { get; set; }
    }
    

    INamingContainerインターフェイスにはメンバーがなく、クラスを何かとしてマークするためにのみ使用されますUserControl

  5. これで完了です3。このコントロールを aspx ページで使用できるようになりました。ただし、最初にaspx ページの上部で「登録」する必要があります。

    <%@ Register src="Contoso.ascx" TagName="Contoso" tagprefix="uc" %>
    

    どこ:

    • Contoso.ascxascxファイルの名前です
    • Contosoこのユーザー コントロールを参照するために使用する要素の名前です。
    • uc前に置く必要があるテキストですuc:Contoso(私はuser-control のuc略として使用します)
  6. コントロールをページに追加します。

    <uc:Contoso ID="Crackers" runat="server">
        <ContentTemplate>
            Stuff goes here
        </ContentTemplate>
    </qwerty:Contoso>
    

これで完了です。4

編集:上記が機能しない理由を追加するのを忘れました。Visual Studio に次のエラーが表示されます。

コントロール作成エラー - クラッカー

タイプ 'System.Web.UI.UserControl' には 'ContentTemplate' という名前のパブリック プロパティがありません

ここに画像の説明を入力

UserControlという名前のパブリック プロパティがないため、これは理にかなってContentTemplateいます。

シリーズ

この質問は、進行中の Stackoverflow シリーズ「ユーザー コントロールのテンプレート化」の 1 つです。

ボーナスリーディング

脚注

  • 1その構文は使用できません。読みやすく、理解しやすいフォームです。
  • 2どの属性を追加すればよいのか、またその理由は誰にもわかりません。味に多かれ少なかれ属性を追加します。
  • 3行われていません。UserControl は完了しましたが、私たちの作業ではありません。
  • 4完了していません。うまくいきません。
  • 5 Web サイト (Web アプリケーションではなく、別のアセンブリではありません)
4

1 に答える 1

13

まあ、私はあなたがほとんどそれを手に入れたと信じています。

ところで。UserControl は Visual Studio Designer を使用してレンダリングされませんが、アプリケーションを実行するとコントロールは機能します。代わりにサーバー コントロールを使用する場合は異なります。その場合、コントロールは Visual Studio デザイナーで正しく表示されます。

次のコードは、テンプレート化されたユーザー コントロールとテンプレート化されたサーバー コントロールを構築するのに最適ですが、バインディング機能を追加する場合は、プロセスが少し異なります。

ソースコードをダウンロード

これは、テンプレート化された を作成するためのコードUserControlです。

簡易出力

ここに画像の説明を入力

テンプレートコンテナ

public class MyTemplateContainer : Control, INamingContainer { }

ASPX コードビハインド

protected void Page_Load(object sender, EventArgs e)
{
    // just to demonstrate using the contorl
    this.WebUserControl1.Controls.Add(new LiteralControl("<br />new control"));
}

ASPX

<%@ Register src="WebUserControl.ascx" tagname="WebUserControl" tagprefix="uc1" %>

    <uc1:WebUserControl ID="WebUserControl1" runat="server">
        <ContentTemplate>
            My Template<br />
            <asp:Label Text='Hello People' runat="server" ID="lblMessage" />
        </ContentTemplate>
    </uc1:WebUserControl>

ASCX コードビハインド

public partial class WebUserControl : System.Web.UI.UserControl
{
    [TemplateContainer(typeof(MyTemplateContainer))]
    [TemplateInstance(TemplateInstance.Single)]
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [Browsable(true)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    public ITemplate ContentTemplate { get; set; }

    protected void Page_Init(object sender, EventArgs e)
    {
        this.myPlaceHolderTag.Controls.Clear();

        if (this.ContentTemplate != null)
        {
            var container = new MyTemplateContainer();

            this.ContentTemplate.InstantiateIn(container);
            this.myPlaceHolderTag.Controls.Add(container);
        }
        else
        {
            this.myPlaceHolderTag.Controls.Add(new LiteralControl("No template defined"));
        }
    }
}

ASCX

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="WebUserControl.ascx.cs" Inherits="WebUserControl" %>

<asp:PlaceHolder runat="server" ID="myPlaceHolderTag" />

テンプレート化されたサーバー コントロールを追加するコード

出力

ここに画像の説明を入力

ASPX

<%@ Register Namespace="MyControls" TagPrefix="my" %>

<my:MyServerControl runat="server" ID="myServerControl">
    <ContentTemplate>
        My Server templated control<br />
        <asp:Label Text="My Label" runat="server" />
    </ContentTemplate>
</my:MyServerControl>

テンプレートコンテナ

namespace MyControls
{
    [ToolboxItem(false)]
    public class MyTemplateContainer : Control, INamingContainer { } 
}

テンプレート化されたサーバー コントロール

namespace MyControls
{
    [ToolboxData("<{0}:MyServerControl runat=server >")]
    [ToolboxItem(true)]
    [ParseChildren(true)]
    // you can inherit from another control if you like, for example from the CompositeControl
    public class MyServerControl : Control, INamingContainer
    {
        [TemplateInstance(TemplateInstance.Multiple)]
        [TemplateContainer(typeof(MyTemplateContainer))]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [DefaultValue(null)]
        public ITemplate ContentTemplate { get; set; }

        protected override void CreateChildControls()
        {
            var p = new Panel { ID = "myPanel", BackColor = Color.Silver, Width = new Unit("100%") };

            if (this.ContentTemplate == null)
            {
                p.Controls.Add(new LiteralControl("No content has been specified"));
            }
            else
            {
                var c = new MyTemplateContainer();

                this.ContentTemplate.InstantiateIn(c);
                p.Controls.Add(c);
            }

            this.Controls.Clear();
            this.Controls.Add(p);
        }

        public override void DataBind()
        {
            this.CreateChildControls();
            this.ChildControlsCreated = true;
            base.DataBind();
        }

        public override ControlCollection Controls
        {
            get
            {
                this.EnsureChildControls();
                return base.Controls;
            }
        }
    }
}

参考文献:

于 2012-07-28T11:17:59.090 に答える