1

我是新来的,但在寻找答案时我已经浏览了一段时间的 stackoverflow。

这是问题所在:我正在尝试使用多个条件模板实现自定义转发器,以避免模板中的尽可能多的测试

至于现在我的 ascx 代码看起来像这样:

<custom:Repeater runat="server">
    <headerTemplate>...</headerTemplate>
    <templates>
    <custom:template match="[filter1]"><contents>[filter1] is true for <%# Container.DataItem.ID%></contents></custom:template>
    <custom:template match="[filter2]"><contents>[filter2] is true for <%# Container.DataItem.ID%></contents></custom:template>
    </templates>
</custom:Repeater>

除了这种语法太冗长之外,以下代码有效

<custom:template match="[filter1]"><contents><%# TypeOf Container is IDataItemContainer%></contents></custom:template>

但是这段代码失败了

<custom:template match="[filter1]"><contents>[filter1] is true for <%# Container.DataItem.ID%></contents></custom:template>

我收到错误消息::“DataItem”不是“System.Web.UI.Control”的成员。似乎 vb 试图在编译时而不是在数据绑定时解析模板内容

这是我的vb课程

<ParseChildren(True, "contents")>
Public Class Template : Inherits WebControl : Implements ITemplate
    Private _match As String
    <PersistenceMode(PersistenceMode.Attribute)>
    Public Property match() As String
        Get
            Return _match
        End Get
        Set(ByVal value As String)
            'TODO compile filter as an expression
            _match = value
        End Set
    End Property

    Private _source As ITemplate
    <PersistenceMode(PersistenceMode.Attribute)>
    Public Property contents() As ITemplate
        Get
            Return Nothing
        End Get
        Set(ByVal value As ITemplate)
            _source = value
        End Set
    End Property

    Public Sub InstantiateIn(container As System.Web.UI.Control) Implements System.Web.UI.ITemplate.InstantiateIn
        _source.InstantiateIn(container)
    End Sub
End Class

<ParseChildren(True)>
Public Class ApplyTemplate : Inherits Repeater

    _template as List(Of Template)
    <PersistenceMode(PersistenceMode.InnerProperty), TemplateContainerAttribute(GetType(Template))>
    Public Overloads Property templates() As List(Of Template)
        Get
            Return Nothing
        End Get
        Set(value As List(Of Template))
            _templates = value
        End Set
    End Property

End Class

如何在模板的内容中添加数据绑定表达式?

提前致谢。

最大限度。

PS:是否有可能(以及如何;))压缩 ascx 代码,使其看起来像这样:

<custom:Repeater runat="server">
    <headerTemplate>...</headerTemplate>
    <custom:template match="[filter1]">[filter1] is true for <%# Container.DataItem.ID%></custom:template>
    <custom:template match="[filter2]">[filter2] is true for <%# Container.DataItem.ID%></custom:template>
    ...
</custom:Repeater>
4

1 回答 1

0

最后我有时间再次处理这个问题,感谢这个链接(http://www.codeproject.com/Articles/21521/Creating-a-Templated-User-Control)我能够实现我自己的自定义转发器我想。

所以现在aspx代码看起来像这样

<custom:Repeater runat="server" >
    <headerTemplate>...</headerTemplate>
    <separatorTemplate on="1,9">some advertisement snippet</separatorTemplate>
    <separatorTemplate every="2"><hr/></separatorTemplate>
    <itemTemplate match="[filter1]"><source>[filter1] is true for <%# Container.DataItem.ID%></source></itemTemplate>
    <itemTemplate match="[filter2]"><source>[filter2] is true for <%# Container.DataItem.ID%></source></itemTemplate>
    ...
</custom:Repeater>

如果需要,仍然需要内部源标记以允许模板中的代码块。如果有人知道如何删除它并仍然保留具有元数据属性的功能,请发表评论。

所以对于vb代码,这里是类骨架

Public Class Repeater
    Inherits System.Web.UI.UserControl ' I use a UserControl so i can add support any html-bound attributes like class, style, data-*... without hardcoding them in the class

    Private templates As New List(Of TemplateItem)
    <PersistenceMode(PersistenceMode.InnerProperty)>
    Public WriteOnly Property itemTemplate() As TemplateItem
        Set(value As TemplateItem)
            value.Container = Me 'to bind the container to the template instead of passing the reference on instanciation
            templates.Add(value)
        End Set
    End Property

    Public Overrides Sub DataBind()
        If Not IsNothing(datasource) Then 'this to avoid nested controls Databind method to be called twice
            [... iterate on dataitems]
            [... template selection on best matching filters]
                templates.instantiateFor(dataitem) ' to instanciate the template for the current item
            [... iteration done]
            MyBase.DataBind() ' to bind the newly created controls
        End If
    End Sub
    ...
End Class

'
<ParseChildren(True, "source")>
Public Class TemplateItem
    Inherits Control

    Friend Container As Repeater

    'handle as many attributes as you want here
    Private _matchExpression As String
    <PersistenceMode(PersistenceMode.Attribute)>
    Public Property match() As String
        Get
            Return _matchExpression
        End Get
        Set(value As String)
            _matchExpression = value
        End Set
    End Property

    'Now the simple part for parsing the inner code has a template
    'I use the standard RepeaterItem class as the template container because i don't need more features for now
    Private _source As ITemplate
    <PersistenceMode(PersistenceMode.InnerDefaultProperty)>
    <TemplateContainer(GetType(RepeaterItem))>
    Public Property source() As ITemplate
        Get
            Return _source
        End Get
        Set(value As ITemplate)
            _source = value
        End Set
    End Property

    'now the part to instantiate as template for a given item
    Public Sub instantiateFor(Item As Object, Optional itemIndex As Integer = -1)
        Dim instantiator = New RepeaterItem(itemIndex, ListItemType.Item)
        instantiator.DataItem = Item
        _source.InstantiateIn(instantiator)
        Container.Controls.Add(instantiator)
    End Sub
End Class

等等等等……终于!!希望这会有所帮助

于 2013-04-13T12:47:12.870 回答