カスタムASP.NETコンテナーコントロール
-
08-07-2019 - |
質問
いくつかのdivで囲まれているなど、Panelコントロールとまったく同じように機能するカスタムコントロールを作成して、丸みのあるボックスの外観を作成しようとしています。これを行う方法の適切な例を見つけることができませんでした。
テキストとコントロールをコントロール内に配置し、パネルを参照せずに直接アクセスできるようにする必要があります(Panelコントロールの動作方法)。
この例はありますか?
解決
これを行うには2つの方法があります。 1つは、コントロールにINamingContainerを実装することです。これには多くの労力が必要です。
もう1つの方法は、Panelから継承し、RenderBeginTagおよびRenderEndTagメソッドをオーバーライドしてカスタムマークアップを追加することです。これは簡単です。
public class RoundedCornersPanel : System.Web.UI.WebControls.Panel
{
public override RenderBeginTag (HtmlTextWriter writer)
{
writer.Write("Your rounded corner opening markup");
base.RenderBeginTag(writer);
}
public override RenderEndTag (HtmlTextWriter writer)
{
base.RenderEndTag(writer);
writer.Write("Your rounded corner closing markup");
}
}
他のヒント
すでに多くの回答がありますが、Panelクラスから継承せずに、これの最も基本的な実装を貼り付けたいだけです。だからここに行きます:
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
[ToolboxData("<{0}:SimpleContainer runat=server></{0}:SimpleContainer>")]
[ParseChildren(true, "Content")]
public class SimpleContainer : WebControl, INamingContainer
{
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(SimpleContainer))]
[TemplateInstance(TemplateInstance.Single)]
public virtual ITemplate Content { get; set; }
public override void RenderBeginTag(HtmlTextWriter writer)
{
// Do not render anything.
}
public override void RenderEndTag(HtmlTextWriter writer)
{
// Do not render anything.
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("<div class='container'>");
this.RenderChildren(output);
output.Write("</div>");
}
protected override void OnInit(System.EventArgs e)
{
base.OnInit(e);
// Initialize all child controls.
this.CreateChildControls();
this.ChildControlsCreated = true;
}
protected override void CreateChildControls()
{
// Remove any controls
this.Controls.Clear();
// Add all content to a container.
var container = new Control();
this.Content.InstantiateIn(container);
// Add container to the control collection.
this.Controls.Add(container);
}
}
その後、次のように使用できます:
<MyControls:SimpleContainer
ID="container1"
runat="server">
<Content>
<asp:TextBox
ID="txtName"
runat="server" />
<asp:Button
ID="btnSubmit"
runat="server"
Text="Submit" />
</Content>
</MyControls:SimpleContainer>
そしてコードビハインドから、次のようなことができます:
this.btnSubmit.Text = "Click me!";
this.txtName.Text = "Jack Sparrow";
System.Web.UI.Controlを継承するクラスを作成し、Render(HtmlTextWriter)メソッドをオーバーライドします。 このメソッドでは、周囲の開始タグをレンダリングしてから、children(RenderChildren)をレンダリングしてから、終了タグをレンダリングします。
protected override void Render ( HtmlTextWriter output )
{
output.Write ( "<div>" );
RenderChildren ( output );
output.Write ( "</div>" );
}
丸い角は通常、CSSと左上、右上、左下、右下の角の角の画像を使用して実現されます。 レイヤーとして機能する4つのネストされたdivを使用して実行できます。各divは背景画像として1つのコーナー画像を持ちます。
コードプロジェクトには、興味のあるものがあります:パネルカーブコンテナ-ASP .NETカスタムコントロールナゲット。あなたはコードで遊んで、あなたが望む振る舞いと外観を持っていると確信しています。
PanelからではなくWebControlから直接継承したくない場合、これを行う最も簡単な方法は、クラスを属性 [ParseChildren(false)]
で装飾することです。一見すると、これは子を解析したくないことを示唆するかもしれませんが、 false
が実際に示しているのは、子をプロパティとして扱いたくないということです。代わりに、それらをコントロールとして処理する必要があります。
この属性を使用することにより、ほぼすべての機能をすぐに使用できます:
[ToolboxData("<{0}:RoundedBox runat=server></{0}:RoundedBox>")]
[ParseChildren(false)]
public class RoundedBox : WebControl, INamingContainer
{
public override void RenderBeginTag(HtmlTextWriter writer)
{
writer.Write("<div class='roundedbox'>");
}
public override void RenderEndTag(HtmlTextWriter writer)
{
writer.Write("</div>");
}
}
これにより、RoundedBoxコントロールをページに追加し、div内にレンダリングされる子(asp.netコントロールまたは生のhtml)を追加できます。
もちろん、roundedboxクラスのスタイルを正しく設定するためにcssが追加されます。
もう1つ使用できるのは、角の丸いエクステンダー ASP.Net ajaxツールキット。
それはあなたが求めていたものとは正確に異なりますが、カスタムコードを記述する必要はありません。
役立つことを願っています!
この質問を見たのは、2列のレイアウトパネルを作成したかったからです。 (完全ではありませんが、必要なもののはるかに単純な例です。私が使用して作成したソリューションを共有しています:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Syn.Test
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:MultiPanel runat=server></{0}:MultiPanel>")]
[ParseChildren(true)]
[PersistChildren(false)]
public class MultiPanel : WebControl, INamingContainer
{
public ContentContainer LeftContent { get; set; }
public ContentContainer RightContent { get; set; }
protected override void CreateChildControls()
{
base.CreateChildControls();
}
protected override void Render(HtmlTextWriter output)
{
output.AddStyleAttribute("width", "600px");
output.RenderBeginTag(HtmlTextWriterTag.Div);
output.AddStyleAttribute("float", "left");
output.AddStyleAttribute("width", "280px");
output.AddStyleAttribute("padding", "10px");
output.RenderBeginTag(HtmlTextWriterTag.Div);
LeftContent.RenderControl(output);
output.RenderEndTag();
output.AddStyleAttribute("float", "left");
output.AddStyleAttribute("width", "280px");
output.AddStyleAttribute("padding", "10px");
output.RenderBeginTag(HtmlTextWriterTag.Div);
RightContent.RenderControl(output);
output.RenderEndTag();
output.RenderEndTag();
}
}
[ParseChildren(false)]
public class ContentContainer : Control, INamingContainer
{
}
}
私がまだ抱えている問題は、このシナリオではインテリセンスが機能しないことです。左コンテンツタグと右コンテンツタグを提案しません。
public class myCustomPanel : Panel
{
public override void RenderBeginTag(HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Class, "top_left_corner");
writer.RenderBeginTag(HtmlTextWriterTag.Div);
base.RenderBeginTag(writer);
}
public override void RenderEndTag(HtmlTextWriter writer)
{
base.RenderEndTag(writer);
writer.RenderEndTag();
}
}