分层 Repeater 和配套附件






4.86/5 (9投票s)
一个分层重复器控件。
引言
我正在处理一个需要纯粹使用 DIV 渲染站点地图数据的解决方案。在最初的编码中,我尝试使用标准 TreeView 控件,例如 ASP.NET 的 TreeView
和其他第三方控件。但它们都不允许该项目所需的自定义渲染逻辑。大多数树视图或树控件实现自己的渲染逻辑,这会破坏您的设计规则。有时候没有“我们不能使用现有的吗?”,当所有方法都尝试过后,我只能通过编码来解决它!!!嵌套 Repeater
看起来很有道理,但编码会变得很丑陋,因为不知道每个树的深度。遍历 Render
方法中的数据是最终采用的解决方案。(现在尝试让你的 HTML 工程师来修复那个的样式吧 :-))。
解决方案完成后,我决定使用 ASP.NET 2.0 的 HierarchicalDataBoundControl
基类构建一个 HierarchicalRepeater
控件,并允许完全自定义分层数据的 HTML 样式和布局,而不是覆盖所用控件的 Render
方法。
所以我有我的目标,但从哪里开始呢?
以下是我希望在构建此控件时要解决的问题的列表
- 写下我的第一篇 CodeProject 文章。
- 允许完全控制模板中的渲染逻辑。
- 能够在分层结构内的每个深度定义多个模板。
- 允许 DataBinding 表达式
<%#Eval("SomeProperty")%>
IHierarchicalEnumerable
和 IHierarchyData
接口将任何对象定义为分层的。HierarchicalRepeater 控件的结构
我首先定义了一个模板基础设施,它允许迭代分层数据
<asp:SiteMapDataSource ID="SiteMapDataSource1"
runat="server" SiteMapProvider="MenuProvider" />
<cc1:HierarchicalRepeater runat="server" ID="repeater">
<ItemHeaderTemplate><ul></ItemHeaderTemplate>
<ItemTemplate><li><%#Eval("Title") %></li></ItemTemplate>
<ItemFooterTemplate></ul></ItemFooterTemplate>
</cc1:HierarchicalRepeater>
使用此结构,我能够创建以下 HTML
- Home
- Node1
- Node1 1
- Node1 2
- Node1 3
- Node2
- Node2 1
- Node2 2
- Node2 3
- Node3
- Node3 1
- Node3 2
- Node3 3
- Node3 4
- Node3 4 1
允许发生此情况的核心函数是 CreateControlHierarchyRecursive
方法
protected virtual void CreateControlHierarchyRecursive(IHierarchicalEnumerable dataItems)
分层数据源依赖于能够递归地迭代其节点。 HierarchicalRepeater
通过调用 CreateControlHierarchyRecursive
来实现这一点,如果检测到当前数据项有子项。这意味着可以完全遍历数据源。
但后来我开始思考,“太棒了,我有一个 HierarchicalRepeater
控件,但每个节点深度自定义渲染样式呢?” 在 Danny Chen 的文章的帮助下,我按照他的解决方案创建了 CustomTemplate,然后将其包装到一个集合中以在 Repeater
控件中使用。 ItemTemplate
控件允许您指定希望覆盖的深度和 ListItemType
。当每个深度都有自己的渲染逻辑时,或者过滤渲染特定深度时,这很有帮助,当有必要省略渲染超出某个深度的深层子节点时。
使用 TemplateCollection 的分层重复器控件
以下代码为 SiteMap 中的每个深度渲染不同的颜色。如果您注意到,我只有一个项目页脚模板,该模板将用于所有对应的项目模板。
<cc1:HierarchicalRepeater runat="server"
ID="repeater" Width="231px">
<TemplateCollection>
<cc1:ItemTemplate Depth="0" ListItemType="ItemTemplate">
<Template>
<div style="padding-left:10px;border: 1px solid blue; background: blue;">
<%#Eval("Item.Value") %>
</Template>
</cc1:ItemTemplate>
<cc1:ItemTemplate Depth="1" ListItemType="ItemTemplate">
<Template>
<div style="padding-left:10px;border: 1px solid red; background: red;">
<%#Eval("Item.Value") %>
</Template>
</cc1:ItemTemplate>
<cc1:ItemTemplate Depth="2" ListItemType="ItemTemplate">
<Template>
<div style="padding-left:10px;border: 1px solid red; background: green;">
<%#Eval("Item.Value") %>
</Template>
</cc1:ItemTemplate>
</TemplateCollection>
//Default ItemFooterTemplate used for all
<ItemFooterTemplate>
</div>
</ItemFooterTemplate>
</cc1:HierarchicalRepeater>
HierarchyData<ListItem> root =
new HierarchyData<ListItem>(new ListItem("Root", "Root"), null);
HierarchyData<ListItem> child1 =
new HierarchyData<ListItem>(new ListItem("Child1", "child1"),root);
HierarchyData<ListItem> child2 =
new HierarchyData<ListItem>(new ListItem("Child2", "child2"),root);
HierarchyData<ListItem> child2_1 =
new HierarchyData<ListItem>(new ListItem("Child2_1", "child2_1"),child2);
HierarchyDataCollection<HierarchyData<ListItem>> coll =
new HierarchyDataCollection<HierarchyData<ListItem>>();
coll.Add(root);
repeater.DataSource = coll;
repeater.DataBind();
控件的渲染输出
您代码中那个泛型 HierarchyData<T> 是什么?
只有少数实现 IHierarchicalEnumerable 的 HierarchicalDatabound
控件或类。两个值得注意的控件是 XMLDataSource
和 SiteMapDatasource
,以及一些与两个数据源控件结合使用的类。当然,由于我试图向您推销我的 HierarchicaRepeater
控件,因此很自然地,我为您提供了一种机制,可以使用您自己的对象来创建分层数据,而不是您编写 IHierarchyData
和 IHierarchicalEnumerable
的所有管道代码。只有在大量使用泛型进行集合和列表之后,我才意识到泛型的强大之处。我对 HierarchyData<T>
的尝试是您开始创建自己的分层数据源所需要的所有管道。因此,使用 HierarchicalRepeater
和 HierarchyData<T>
,您现在可以创建和渲染复杂的分层数据源,并完全控制数据的渲染。