2

我正在尝试将模板添加到包含标签和文本框的简化复合控件。我希望我的标记看起来像这样:

<test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
    <TestTemplate>
        <i>
            <%# Container.Title) %></i>
        <br />
        <%# Container.Text %>
    </TestTemplate>
</test:FormItem> 

我有一个 templateContainer 类,它具有 TextBox 和 Label 的属性。

public class TemplateContainer : WebControl, INamingContainer
{

    public TextBox Text { get { return m_item.Text; } }
    public Label Title { get { return m_item.Title; } }

    private FormItem m_item;

    public TemplateContainer(FormItem item)
    {
        m_item = item;
    }

}

在主 FormItem 类中,我有一个从 CreateChildControls() 调用的 CreateControlHierarchy() 方法:

protected virtual void CreateControlHierarchy()
    {

        m_itemTemplateContainer = new TemplateContainer(this);
        TestTemplate.InstantiateIn(m_itemTemplateContainer);

        Controls.Add(m_itemTemplateContainer);

    }

我想要的是模板呈现实际控制。相反,它在控件上调用 ToString() 并显示 System.Web.UI.WebControls.Label 和 System.Web.UI.WebControls.TextBox。有没有办法让模板将控件添加到它的集合中,而不仅仅是在它们上调用 ToString() ?

注意:我还尝试将文本框和标签添加到执行相同操作的容器的控件集合中。

4

2 回答 2

1

行。所以我尝试了一些事情,我想出了一个好的解决方案。

首先,我尝试在数据绑定表达式中使用方法,然后跟踪文本框或标签在容器的 Control 集合中的位置。但是,CompiledTemplateBuilder(这是 .Net 内部为标记中指定的 ITemplates 构建的内容)将两个绑定表达式之前和之后的所有标记放入一个 DataBoundLiteral 控件中,并且在调用该方法时已经构建了 Control 集合。

起作用的是创建一个新的 WebControl,它充当复合控件中控件的占位符。它有一个属性 Control,当设置时,它将控件添加到它的 Controls 集合中。

public class FormItemPlaceHolder : WebControl, INamingContainer
{
    public WebControl Control
    {
        get
        {
            if(Controls.Count == 0)
                return null;
            return Controls[0] as WebControl;
        }
        set
        {
            if (Controls.Count != 0)
                Controls.Clear();
            Controls.Add(value);
        }
    }

}

然后在标记中,我创建了一个这种类型的控件并将它的 Control 属性绑定到容器中的正确属性。

<test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
    <TestTemplate>
        <i>
        <test:FormItemPlaceHolder ID="ph" runat="server" 
            Control='<%# Container.Title %>' />
        </i>
        <br />
         <test:FormItemPlaceHolder ID="ph2" runat="server" 
             Control='<%# Container.Text %>' />
    </TestTemplate>
</test:FormItem>

有没有人有更好的解决方案?

于 2009-03-05T20:48:45.783 回答
0

容器不应该定义控件,只定义数据。

您应该在标记中定义数据的实际控件,并为它们分配容器中的值。

例如

public class TemplateContainer : UserControl
{
    public string Text { get { return m_text; } }
    public string Title { get { return m_title; } }

    private string m_text;
    private string m_title;
    private FormItem m_item;

    public TemplateContainer(FormItem item)
    {
        m_item = item;
    }

}

在标记中:

   <test:FormItem ID="fi" runat="server" Title="MyTitle" Text="My Text!">
        <TestTemplate>
            <i><asp:Label runat="server" Text='<%# Container.Title) %>' /></i>
            <br />
            <asp:TextBox runat="server" Text='<%# Container.Text %>' />
    </TestTemplate>
</test:FormItem>

如果您尝试创建不需要在标记中添加控件的复合控件,那么您为什么要使用模板?如果只是为了造型,那么创建自己的 Style 对象可能更有效?

于 2009-03-11T00:09:23.933 回答