【问题标题】:Repeater control - Cancel bind for specific item中继器控制 - 取消特定项目的绑定
【发布时间】:2010-02-08 14:30:56
【问题描述】:

在转发器控件中,有没有办法在页面呈现之前解除对某些项目的绑定?

目前我们有一个绑定到转发器的项目集合,如果项目不是当前语言的一部分,我们将隐藏该项目。

我希望能够对中继器进行计数并获得一个有效的数字。不包括隐藏项的计数。

是否可以在 ItemDataBound 事件中解除特定项目的绑定?

更新

对于我们正在绑定的集合中的每个项目,我们会在ItemDataBound 期间检查数据库以获取有关该项目的更多信息,例如语言等。这目前阻止我们在绑定之前过滤绑定的数据。

【问题讨论】:

    标签: asp.net binding repeater


    【解决方案1】:

    如果这些隐藏项中没有特定需求,则更合适的解决方案可能是过滤绑定集合。类似的东西

    items.Where(i => i.IsInLanguage(currentLanguage));
    

    更新:

    就我而言,我会使用这种方法:

    var items = db.
          Where(i => i.IsInLanguage(currentLanguage)).
          Where(i => i.SomeField == anotherFilterParameter);
    
    repeater.DataSource = items;
    repeater.DataBind();
    

    所以所有过滤都是预先应用的

    这也将减少到数据库的往返次数,从而提高性能

    【讨论】:

    • 我将更新我的 OQ,但基本上,在 ItemDataBound 事件之前,我们不知道将哪些项目设置为可见等。每个项目都有一个 ID,然后我们会去数据库获取更多详细信息。
    • ItemDataBound 上发生了什么使得过滤成为可能?您当前的语言是否仅在那时才可用?
    • 是的。基本上,我们有一个称为“页面”ID 集合的东西,当每个项目被绑定时,我们进入数据库,找出它是否是当前语言的一部分,如果不是,隐藏项目。
    • 是否可以在绑定前获取item的id并查询数据库这次哪些id合适?
    • 每次数据绑定时查询数据库的性能原因也不好
    【解决方案2】:

    我同意其他答案 - 最好的解决方案(性能和代码清晰度)是重新设计页面,以便您可以在 数据绑定之前过滤掉无效条目。

    大多数数据源不允许我们在 ASP.NET 迭代它们时删除它们的项目。例如,如果您绑定到一个简单的泛型 List<T>,并在迭代时删除了一个项目,则列表将抛出一个 InvalidOperationException

    在其他情况下,ASP.NET 实际上会迭代数据源的副本。如果绑定到DataTable,ASP.NET 将使用内容的副本(默认 DataView)而不是迭代源行本身 - 您可以在迭代时从基础数据源中删除项目,但这不会影响数据绑定操作。

    如果确实无法提前过滤项目,那么您当前的解决方案很好:只需隐藏项目!如果您需要在此基础上获得正确的计数,请跟踪 ItemDataBound 处理程序中无效项目的数量并将其公开为页面级属性:

    if (IsInvalid(args.Item.DataItem)) {
        this.invalidItemCount++;
        // code to hide the current item
    }
    

    【讨论】:

    • 我很想重新设计页面的工作方式,但我们使用 EPiServer 作为 CMS,据我所知,目前的方式是我能找到的最好的方式.我目前正在遵循您最后的建议,以公开 Count 属性并将其添加为有效项目。可能不得不坚持下去。感谢您的回复:)
    【解决方案3】:

    为什么不在绑定前过滤数据源。所以假设你正在使用一些自定义对象:

    myRepeater.DataSource=repository.getItems().Where(item=>item.Language==CurrentLanguage);
    

    如果您不需要它们,请不要首先绑定它们。

    更新

    如果有可能,您应该提前从数据库中提取该信息。这些列表很大吗?如果是这样,为列表中的每个项目点击一次数据库将显示为性能问题。

    【讨论】:

      【解决方案4】:

      答案很简单,您只需将项目上的Visible 属性设置为false,它就不会被渲染。在此示例中,如果当前用户有购买历史记录,我将从产品列表中删除仅对新客户可用的项目:

      void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
              {
                  if (!userHasPurchaseHistory) { return; }
                  // filter out products only allowed for new members
                  if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                  {
                      System.Data.Common.DbDataRecord rec = (System.Data.Common.DbDataRecord)e.Item.DataItem;
                      if (rec != null)
                      {
                          bool newMemberOnly = Convert.ToBoolean(rec["NewMemberOnly"]);
                          if (newMemberOnly) { e.Item.Visible = false; }
                      }
                  }
      
              }
      

      请注意,以上数据绑定到 IDataReader,您可能需要将 e.Item.DataItem 转换为不同的对象,具体取决于您绑定的对象。

      还要注意,我绝对不会在绑定时进行另一个数据库查找,你不应该在循环中访问数据库,但只要你绑定的数据有一些东西你可以检查以确定是否要显示它在ItemDataBound 中过滤没有任何问题。如果您正在执行任何类型的分页,则可能会出现问题,因为这会导致呈现不一致的页面大小。

      【讨论】:

        猜你喜欢
        • 2014-11-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多