我是新来的,但在寻找答案时,我一直在浏览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>
答案 0 :(得分: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
Etvoilà...终于!! 希望这会有所帮助