2010-02-08 60 views
7

在中继器控件中,是否有某种方法在页面呈现之前解除某些项目的绑定?中继器控制 - 取消特定项目的绑定

当前我们有一组物品被绑定到一个转发器,如果​​该物品不是当前语言的一部分,我们会隐藏该物品。

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

是否有可能去绑定特定项目或许在ItemDataBound事件?

更新

对于我们结合集合中的每个项目,我们的ItemDataBound有关项目的详细信息,如语言等,这期间检查数据库正在阻止我们过滤绑定绑定它之前的数据。

回答

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 
} 
+0

我很想重新设计页面的工作方式,但我们使用EPiServer作为CMS,据我所知,目前方式是我能找到的最好的方式。我目前正在追踪你的最后一次泄露,暴露一个Count属性并将其变为有效项目。可能必须坚持这一点。谢谢回复 :) – 2010-02-08 15:48:53

3

如果这些隐藏项目中没有特定需要,则更合适的解决方案可以是过滤绑定集合。喜欢的东西

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

更新:

至于我,我想用这个办法:

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

repeater.DataSource = items; 
repeater.DataBind(); 

因此,所有过滤事先

应用这将减少廿四数旅行到数据库,以及更好的性能

+0

我会更新我的OQ,但基本上,我们不知道哪些项目设置为可见等直到ItemDataBound事件。每个项目都有一个ID,然后我们到数据库获取额外的细节。 – 2010-02-08 14:37:42

+0

ItemDataBound会发生什么,使过滤成为可能?您目前的语言是否仅在当时可用? – 2010-02-08 14:39:07

+0

是的。基本上我们有一些称为“页面”ID的集合,并且在绑定每个项目时,我们转到数据库,查明它是否是当前语言的一部分,如果不是,则隐藏该项目。 – 2010-02-08 14:40:21

2

为什么不过滤呃绑定之前的数据源。因此,假如你使用的是一些自定义对象:

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

如果你不需要他们不摆在首位约束力。

更新

如果这是在所有可能你应该probally拉从DB前期该信息。这些清单很大吗?如果在列表中每个项目敲击一次数据库都会显示为性能问题。

2

答案是很容易的,你只需设置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中过滤没有任何问题。如果您正在进行任何类型的分页,这可能会造成问题,因为这会导致呈现不一致的页面大小。