repeater嵌套的性能问题如何优化?老手分享实用技巧!

吉云

最近手头有个活儿,需要展示一个列表,列表里头,每一项又包含一个小列表。比如说,显示一些分类,然后每个分类下面再列出属于它的小项。这种一层套一层的结构,第一时间我就想到用数据绑定控件来做,能省不少事。

一开始琢磨用哪个控件。像 GridView 这种,虽然功能强,但感觉生成出来的 HTML 结构太固定,都是 table 套 table,有时候为调样式,得写好多 CSS 去覆盖它默认的,挺麻烦。想着 Repeater 这玩意儿它生成的 HTML 干净,基本上就是你模板里写它就生成外面不给你乱加东西,自由度高多。决定就用 Repeater 来搞。

开始动手和遇到的坎

repeater嵌套的性能问题如何优化?老手分享实用技巧!

思路是这样的:外面用一个 Repeater 显示主列表(比如分类),然后在主 Repeater 的项模板(ItemTemplate)里面,再放一个 Repeater,用来显示子列表(比如分类下的小项)。

想法挺撸起袖子就干。先把外层的 Repeater 拖到页面上,设置好数据源,绑定,显示出来,没问题。在它的 `` 里头,放第二个 Repeater,也就是内层的 Repeater。

然后问题就来。外层 Repeater 每一行的数据是有,但内层那个 Repeater 的数据咋办?我当时有点懵,试着在页面加载(Page_Load)的时候给内层 Repeater 找数据源,但发现根本找不到这个内层控件,因为它是在外层 Repeater 的模板里,还没生成。直接在 ASPX 页面里给内层 Repeater 设置 DataSourceID 也不对劲,因为内层的数据是跟外层当前是哪一项挂钩的,不是一个固定的数据源。

捣鼓半天,内层列表就是出不来数据。要么报错,要么就是空的。上网搜搜,也看到不少人问类似的问题,有些答案试下,感觉不太对,或者写得太复杂,看得云里雾里。

找到窍门:关键在事件处理

后来静下心来又琢磨琢磨,觉得关键点应该在于:内层 Repeater 的数据绑定,必须发生在外层 Repeater 处理每一项数据的时候。也就是说,当外层 Repeater 生成第一行时,我得告诉它对应的内层 Repeater 该用哪些数据;生成第二行时,再告诉第二行里的内层 Repeater 用另外的数据。

repeater嵌套的性能问题如何优化?老手分享实用技巧!

顺着这个思路,我想到 Repeater 有个 `ItemDataBound` 事件。这个事件,在外层 Repeater 绑定数据、创建每一项(包括 Header, Footer, Item, AlternatingItem 等)的时候都会触发。这不正好吗?

我赶紧试试这个路子:

  • 给外层的 Repeater 添加 `OnItemDataBound` 事件处理器。就是在 ASPX 页面的 Repeater 标签上加上 `OnItemDataBound="OuterRepeater_ItemDataBound"`,然后在后台代码(.cs 文件)里写这个 `OuterRepeater_ItemDataBound` 方法。
  • 在这个方法里面,得判断当前处理的是不是数据项。因为 HeaderTemplate, FooterTemplate 也会触发这个事件,但我们只关心包含内层 Repeater 的数据项。加上判断:`if (* == * * == *)`。
  • 就在这个 `if` 块里头,通过 `*("InnerRepeaterID")` 来找到当前项里面的那个内层 Repeater 控件。注意,`"InnerRepeaterID"` 是你在 ASPX 里给内层 Repeater 设置的 ID。
  • repeater嵌套的性能问题如何优化?老手分享实用技巧!

  • 找到内层 Repeater 控件后,下一步就是给它找数据。外层 Repeater 当前项的数据可以通过 `*` 拿到。这个 DataItem 通常就是你绑定给外层 Repeater 的数据源里的一个对象。
  • 假设这个对象里有个属性(比如叫 `SubItems`)是一个列表,正好是内层 Repeater 需要显示的数据。那我就从 `*` 里把这个 `SubItems` 列表取出来。
  • 一步,把取出来的数据(`SubItems` 列表)设置给内层 Repeater 的 `DataSource` 属性,然后调用内层 Repeater 的 `DataBind()` 方法。

代码大概就是这个逻辑:

void OuterRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) {

repeater嵌套的性能问题如何优化?老手分享实用技巧!

    if (* == * * == *) {

        // 找到内层 Repeater

        Repeater innerRepeater = (Repeater)*("InnerRepeaterID");

        // 获取外层当前项的数据

        var currentOuterItemData = *;

repeater嵌套的性能问题如何优化?老手分享实用技巧!


        // 从外层数据中提取内层需要的数据 (假设有个 SubItems 属性)

        var innerDataSource = GetSubItemsFromOuterData(currentOuterItemData); // 这里你需要根据实际情况写获取子数据的方法

        // 绑定内层 Repeater

        if (innerRepeater != null && innerDataSource != null) {

repeater嵌套的性能问题如何优化?老手分享实用技巧!

            * = innerDataSource;

            *();

        }

    }

结果和感受

repeater嵌套的性能问题如何优化?老手分享实用技巧!

这么一改,再运行页面,成!外层列表正常显示,每个外层项下面,对应的内层小列表也规规矩矩地显示出来,数据完全正确。

感觉这个方法逻辑很清晰:外层管好自己的一亩三分地,当轮到生成每一项时,再负责把自己这一项里的内层 Repeater 给初始化好、数据绑定各司其职,不乱套。

而且最终生成的 HTML 也很干净,没有像 GridView 那样多余的 table 结构,调整样式方便多。这回实践下来,对 Repeater 的灵活和 `ItemDataBound` 事件的重要性有更深的体会。以后再遇到类似需要嵌套展示数据的场景,这个方法肯定能派上大用场。

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。