65.9K
CodeProject 正在变化。 阅读更多。
Home

分层 Repeater 和配套附件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.86/5 (9投票s)

2006 年 7 月 26 日

CPOL

4分钟阅读

viewsIcon

81799

downloadIcon

665

一个分层重复器控件。

引言

我正在处理一个需要纯粹使用 DIV 渲染站点地图数据的解决方案。在最初的编码中,我尝试使用标准 TreeView 控件,例如 ASP.NET 的 TreeView 和其他第三方控件。但它们都不允许该项目所需的自定义渲染逻辑。大多数树视图或树控件实现自己的渲染逻辑,这会破坏您的设计规则。有时候没有“我们不能使用现有的吗?”,当所有方法都尝试过后,我只能通过编码来解决它!!!嵌套 Repeater 看起来很有道理,但编码会变得很丑陋,因为不知道每个树的深度。遍历 Render 方法中的数据是最终采用的解决方案。(现在尝试让你的 HTML 工程师来修复那个的样式吧 :-))。

解决方案完成后,我决定使用 ASP.NET 2.0 的 HierarchicalDataBoundControl 基类构建一个 HierarchicalRepeater 控件,并允许完全自定义分层数据的 HTML 样式和布局,而不是覆盖所用控件的 Render 方法。

所以我有我的目标,但从哪里开始呢?

以下是我希望在构建此控件时要解决的问题的列表

  • 写下我的第一篇 CodeProject 文章。
  • 允许完全控制模板中的渲染逻辑。
  • 能够在分层结构内的每个深度定义多个模板。
  • 允许 DataBinding 表达式
  • <%#Eval("SomeProperty")%>
  • 使用泛型创建一个分层数据结构,允许开发人员使用 IHierarchicalEnumerableIHierarchyData 接口将任何对象定义为分层的。

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 控件或类。两个值得注意的控件是 XMLDataSourceSiteMapDatasource,以及一些与两个数据源控件结合使用的类。当然,由于我试图向您推销我的 HierarchicaRepeater 控件,因此很自然地,我为您提供了一种机制,可以使用您自己的对象来创建分层数据,而不是您编写 IHierarchyDataIHierarchicalEnumerable 的所有管道代码。只有在大量使用泛型进行集合和列表之后,我才意识到泛型的强大之处。我对 HierarchyData<T> 的尝试是您开始创建自己的分层数据源所需要的所有管道。因此,使用 HierarchicalRepeaterHierarchyData<T>,您现在可以创建和渲染复杂的分层数据源,并完全控制数据的渲染。

参考文献

© . All rights reserved.