C# でカスタム ユーザー コントロールを使い始めたばかりで、ネストされたタグを受け入れるものを作成する方法の例があるかどうか疑問に思っていますか?
たとえば、 を作成するときasp:repeater
に、 のネストされたタグを追加できますitemtemplate
。
C# でカスタム ユーザー コントロールを使い始めたばかりで、ネストされたタグを受け入れるものを作成する方法の例があるかどうか疑問に思っていますか?
たとえば、 を作成するときasp:repeater
に、 のネストされたタグを追加できますitemtemplate
。
これについては、しばらく前にブログ記事を書きました。簡単に言えば、次のマークアップを持つコントロールがあるとします。
<Abc:CustomControlUno runat="server" ID="Control1">
<Children>
<Abc:Control1Child IntegerProperty="1" />
</Children>
</Abc:CustomControlUno>
コントロール内のコードが次の行に沿っている必要があります。
[ParseChildren(true)]
[PersistChildren(true)]
[ToolboxData("<{0}:CustomControlUno runat=server></{0}:CustomControlUno>")]
public class CustomControlUno : WebControl, INamingContainer
{
private Control1ChildrenCollection _children;
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Control1ChildrenCollection Children
{
get
{
if (_children == null)
{
_children = new Control1ChildrenCollection();
}
return _children;
}
}
}
public class Control1ChildrenCollection : List<Control1Child>
{
}
public class Control1Child
{
public int IntegerProperty { get; set; }
}
私はRobのブログ投稿に従い、少し異なるコントロールを作成しました。コントロールは条件付きのものであり、実際にはif句と同じです。
<wc:PriceInfo runat="server" ID="PriceInfo">
<IfDiscount>
You don't have a discount.
</IfDiscount>
<IfNotDiscount>
Lucky you, <b>you have a discount!</b>
</IfNotDiscount>
</wc:PriceInfo>
次に、コードHasDiscount
で、コントロールのプロパティをブール値に設定します。ブール値は、レンダリングされる句を決定します。
Robのソリューションとの大きな違いは、コントロール内の句が実際に任意のHTML/ASPXコードを保持できることです。
そして、これがコントロールのコードです:
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebUtilities
{
[ToolboxData("<{0}:PriceInfo runat=server></{0}:PriceInfo>")]
public class PriceInfo : WebControl, INamingContainer
{
private readonly Control ifDiscountControl = new Control();
private readonly Control ifNotDiscountControl = new Control();
public bool HasDiscount { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Control IfDiscount
{
get { return ifDiscountControl; }
}
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Control IfNotDiscount
{
get { return ifNotDiscountControl; }
}
public override void RenderControl(HtmlTextWriter writer)
{
if (HasDiscount)
ifDiscountControl.RenderControl(writer);
else
ifNotDiscountControl.RenderControl(writer);
}
}
}
最終的に、 Rob (in wayback archive ) @gudmundur-hの回答と非常によく似たものになりITemplate
ましたが、使用法で「X タグの間にコンテンツを配置することはできません」という厄介なものを取り除くために使用していました。実際に何が必要かどうかは完全にはわかりませんので、念のためすべてここに記載します。
mycontrol.ascx
重要な点に注意してください: plcChild1
とplcChild2
.
<!-- markup, controls, etc -->
<div class="shell">
<!-- etc -->
<!-- optional content with default, will map to `ChildContentOne` -->
<asp:PlaceHolder ID="plcChild1" runat="server">
Some default content in the first child.
Will show this unless overwritten.
Include HTML, controls, whatever.
</asp:PlaceHolder>
<!-- etc -->
<!-- optional content, no default, will map to `ChildContentTwo` -->
<asp:PlaceHolder ID="plcChild2" runat="server"></asp:PlaceHolder>
</div>
mycontrol.ascx.cs
[ParseChildren(true), PersistChildren(true)]
[ToolboxData(false /* don't care about drag-n-drop */)]
public partial class MyControlWithNestedContent: System.Web.UI.UserControl, INamingContainer {
// expose properties as attributes, etc
/// <summary>
/// "attach" template to child controls
/// </summary>
/// <param name="template">the exposed markup "property"</param>
/// <param name="control">the actual rendered control</param>
protected virtual void attachContent(ITemplate template, Control control) {
if(null != template) template.InstantiateIn(control);
}
[PersistenceMode(PersistenceMode.InnerProperty),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual ITemplate ChildContentOne { get; set; }
[PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public virtual ITemplate ChildContentTwo { get; set; }
protected override void CreateChildControls() {
// clear stuff, other setup, etc
// needed?
base.CreateChildControls();
this.EnsureChildControls(); // cuz...we want them?
// using the templates, set up the appropriate child controls
attachContent(this.ChildContentOne, this.plcChild1);
attachContent(this.ChildContentTwo, this.plcChild2);
}
}
重要事項 (?):
ParseChildren
-- それで何かが表示されますか?PersistChildren
-- 動的に作成されたものはリセットされませんか?PersistenceMode(PersistenceMode.InnerProperty)
-- そのため、コントロールは正しく解析されますDesignerSerializationVisibility(DesignerSerializationVisibility.Content)
――同上?<%@ Register Src="~/App_Controls/MyStuff/mycontrol.ascx" TagPrefix="me" TagName="MyNestedControl" %>
<me:MyNestedControl SomeProperty="foo" SomethingElse="bar" runat="server" ID="meWhatever">
<%-- omit `ChildContentOne` to use default --%>
<ChildContentTwo>Stuff at the bottom! (not empty anymore)</ChildContentTwo>
</me:MyNestedControl>
このようなものを探していると思いますか?http://msdn.microsoft.com/en-us/library/aa478964.aspx
タグが削除されたか、表示されていないため、実際には役に立ちません。