是否可以通过ASP.NET服务器控件模板中的数据绑定表达式输出Web控件?

时间:2011-11-01 14:15:42

标签: asp.net custom-server-controls servercontrols

我在互联网上搜索这个,包括这里,现在已经有2天了,但我找不到任何类似的问题。另外,这是我在Stack Overflow上的第一篇文章,请耐心等待:]

问题:

这是我第一次真正创建一个模板化服务器控件,但是我在MSDN的帮助下完成了这个模板主题。我已经实现了一个可以像这样使用的控件:

<test:TemplatedControl ID="templatedControl" runat="server">
    <Template>
        Template start:
        <%# Container.EmailText %>
        <%# Container.EmailField %>
        Template end.
    </Template>
</test:TemplatedControl>

控件使用以下容器/上下文作为模板:

public class TemplateContainer : WebControl, INamingContainer
{
    public string EmailText
    {
        get
        {
            return this.emailLabelText;
        }
    }
    string emailLabelText;


    public TextBox EmailField
    {
        get
        {
            return this.emailField;
        }
    }
    TextBox emailField;


    public TemplateContainer()
        : base(HtmlTextWriterTag.Div)
    {
        this.BorderWidth = 2;
        this.BorderStyle = BorderStyle.Outset;

        this.emailLabelText = "E-mail:";

        this.emailField = new TextBox();
        this.emailField.MaxLength = 10;
    }
}

容器类的两个属性都可以正常工作,并且在编写模板时可以通过数据绑定表达式访问,但是EmailField正在呈现为System.Web.UI.WebControls.TextBox,这对于给定的代码是可以的。控件的输出是:

<div style="border-width:2px;border-style:Outset;">
    Template start:
    E-mail:
    System.Web.UI.WebControls.TextBox
    Template end.
</div>

现在问题是:是否可以通过绑定表达式将控件(如此处的TextBox)作为实际控件输出回模板中作为其他数据?

如果可以,那么就可以选择此控件的输出,包括其子控件,并根据需要通过模板将它们放在一起。

我担心这根本不可能实现,但我想让某人澄清这一点。如果是这样的话,我也愿意接受另一种方法的建议。如果您对我尝试这样做的原因感兴趣,请阅读以下内容。

这种方法的原因:

我正在构建一个复合服务器控件,客户自己将在他的网站上使用,该网站仍在开发中。因此,控件输出的最终布局和格式化需求尚不清楚。相反,控件需要在布局和设计方面具有灵活的输出,因此可以对其进行自定义以便以后匹配该站点。

设计部分可以通过为控件设置一些CSS类属性来实现,尽管为客户配置可能很麻烦,因为控件的输出将非常复杂。

我不确定如何实现可自定义的布局要求,例如,在表结构中呈现表单字段,或者在div中呈现它,或者可能只是内联而不需要额外的HTML等。

因此,我没有提供几种预制类型的输出,而是提出了一个想法,即我的控件呈现的输出可能是模板化的,这可以解决布局和设计灵活性问题。客户会声明性地设置一个模板来包装我的模板需要呈现的东西,这也使他能够根据需要将所有的CSS类设置为包装元素。这引出了上述问题和疑问。

提前致谢,

Garkin

1 个答案:

答案 0 :(得分:1)

我认为你需要一个抽象类来定义TemplateContainer需要具备的内容。例如:

public abstract class TemplateContainer : WebControl, INamingContainer
{
    public abstract Literal EmailText { get; }
    public abstract TextBox EmailField { get; }
}

然后要求test:TemplateControl Template实施TemplateContainer

这样您就可以使用EmailTextEmailField来应用MaxLength等。虽然您可能希望在使用之前验证它们不是null

if(EmailText != null)
{
    //use EmailText
}

服务器控件的使用者将创建一个与此类似的控件UserTemplate.ascx

Template start:
<asp:Literal ID="emailText" runat="server" />
<asp:TextBox ID="emailField" runat="server" />
Template end.

代码落后于UserTemplate.ascx.cs

public class UserTemplate : TemplateContainer
{
    public Literal EmailText { get { return emailText; } }
    public TextBox EmailField { get { return emailField; } }
}

---- ----编辑

根据所有这些,包含test:TemplatedControl的页面将会是这样的(假设UserTemplate.ascx的路径别名为test:UserTemplate):

<test:TemplatedControl ID="templatedControl" runat="server">
    <Template>
        <test:UserTemplate ID="userTemplate" runat="server" />
    </Template>
</test:TemplatedControl>

然后在后面的代码中,您可以访问UserTemplate上的属性:

templatedControl.Template.EmailText.Text = "Email: ";
templatedControl.Template.EmailField.MaxLength = 10;