私は関連する質問に答えました:
https://stackoverflow.com/a/11700540/1268570
しかし、この答えでは、私はさらに深く行きます。
設計サポートとカスタム動作を備えたテンプレート化されたサーバーコントロールを投稿します。
コンテナコード
[ToolboxItem(false)]
public class TemplatedServerAddressContainer : WebControl, INamingContainer
{
public string Address { get; protected set; }
public TemplatedServerAddressContainer(string address)
{
this.Address = address;
}
}
- 上記のコントロールは、コントロールに送信するデータをOUTPUTとして保持する役割を果たします。これが、テンプレートをインスタンス化するコントロールになります
サーバー制御
[DefaultProperty("Address")]
[ToolboxItem(true)]
[ToolboxData("<{0}:TemplatedServerAddressControl runate=server></{0}:TemplatedServerAddressControl>")]
[Designer(typeof(TemplatedServerAddressDesigner))]
//[ToolboxBitmap(typeof(TemplatedServerAddressControl), "")]
[Description("My templated server control")]
[ParseChildren(true)]
public class TemplatedServerAddressControl : WebControl
{
private TemplatedServerAddressContainer addressContainer;
[Bindable(true)]
[Localizable(true)]
[DefaultValue(null)]
[Description("The custom address")]
[Category("Apperance")]
[Browsable(true)]
public string Address
{
get
{
return (this.ViewState["Address"] ?? string.Empty).ToString();
}
set
{
this.ViewState["Address"] = value;
}
}
[Browsable(false)]
[DefaultValue(null)]
[Description("Address template")]
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(TemplatedServerAddressContainer))]
[TemplateInstance(TemplateInstance.Multiple)]
public ITemplate AddressTemplate { get; set; }
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TemplatedServerAddressContainer AddressContainer
{
get
{
this.EnsureChildControls();
return this.addressContainer;
}
internal set
{
this.addressContainer = value;
}
}
public override ControlCollection Controls
{
get
{
this.EnsureChildControls();
return base.Controls;
}
}
public override void DataBind()
{
this.CreateChildControls();
this.ChildControlsCreated = true;
base.DataBind();
}
protected override void CreateChildControls()
{
this.Controls.Clear();
if (this.AddressTemplate != null)
{
this.addressContainer = new TemplatedServerAddressContainer(this.Address);
this.AddressTemplate.InstantiateIn(this.addressContainer);
this.Controls.Add(this.addressContainer);
}
}
protected override bool OnBubbleEvent(object source, EventArgs args)
{
if (args is CommandEventArgs)
{
var commandArgs = args as CommandEventArgs;
switch (commandArgs.CommandName)
{
case "DoSomething":
// place here your custom logic
this.Page.Response.Write("Command bubbled");
return true;
}
}
return base.OnBubbleEvent(source, args);
}
}
public string Address
プロパティはコントロールINPUTとして使用され、タスクを実行するために必要なすべての入力プロパティを作成できます。
public ITemplate AddressTemplate { get; set; }
これは、コントロールのテンプレートを表します。このプロパティに付ける名前は、テンプレートの名前としてページのマークアップで使用される名前になります
public TemplatedServerAddressContainer AddressContainer
このプロパティは、デザイナーのサポートのみを目的としています
子コントロールを正しく作成するには、次のメソッドとプロパティをオーバーライドする必要があります。Controls
、DataBind
およびCreateChildControls
をオーバーライドするOnBubbleEvent
と、コントロールからの特定のイベントに反応できるようになります。
デザイナーのサポート
public class TemplatedServerAddressDesigner : ControlDesigner
{
private TemplatedServerAddressControl controlInstance;
public override void Initialize(IComponent component)
{
this.controlInstance = (TemplatedServerAddressControl)component;
base.Initialize(component);
}
public override string GetDesignTimeHtml()
{
var sw = new StringWriter();
var htmlWriter = new HtmlTextWriter(sw);
var controlTemplate = this.controlInstance.AddressTemplate;
if (controlTemplate != null)
{
this.controlInstance.AddressContainer = new TemplatedServerAddressContainer(
this.controlInstance.Address
);
controlTemplate.InstantiateIn(this.controlInstance.AddressContainer);
this.controlInstance.DataBind();
this.controlInstance.RenderControl(htmlWriter);
}
return sw.ToString();
}
}
ASPXマークアップ
<%@ Register Assembly="Msts" Namespace="Msts.Topics.Chapter07___Server_Controls.Lesson02___Server_Controls" TagPrefix="address" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<address:TemplatedServerAddressControl runat="server" ID="addressControl1">
<AddressTemplate>
<b>
Address:
</b>
<u>
<asp:Literal Text="<%# Container.Address %>" runat="server" />
</u>
<asp:Button Text="text" runat="server" OnClick="Unnamed_Click" ID="myButton" />
<br />
<asp:Button Text="Command bubbled" runat="server" CommandName="DoSomething" OnClick="Unnamed2_Click1" />
</AddressTemplate>
</address:TemplatedServerAddressControl>
</asp:Content>
ASPXコードビハインド
public partial class TemplatedServerAddress : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.addressControl1.Address = "Super Cool";
this.DataBind();
}
protected void Unnamed_Click(object sender, EventArgs e)
{
this.Response.Write("From custom button" + DateTime.Now.ToString());
}
protected void Unnamed2_Click1(object sender, EventArgs e)
{
this.Response.Write("From command button " + DateTime.Now.ToString());
}
}
正しいイベントで問題なくコントロールのプロパティを設定する方法に注意してください。this.addressControl1.Address = "Super Cool";
コントロールがカスタムイベントを処理する方法に注目してくださいthis.Response.Write("From custom button" + DateTime.Now.ToString());
そして最後に、何かを実行したいことをコントロールに示すには、次のようにコントロールによって公開されるコマンド名でボタンを作成します。<asp:Button Text="Command bubbled" runat="server" CommandName="DoSomething" OnClick="Unnamed2_Click1" />
オプションで、ボタンには、イベントをバブリングする前に処理されるイベントハンドラーを含めることができます。
このコードサンプルを完全に機能するようにGitHubにアップロードして参照しました