在转发器控件中,是否有一种方法可以在呈现页面之前对某些项目进行解除绑定?
目前我们有一系列项目被绑定到转发器,如果该项目不是当前语言的一部分,我们会隐藏该项目。
我希望能够对转发器进行计数并获得有效数字。计数不包括隐藏项目。
是否可以在ItemDataBound
事件中对特定项目进行解除绑定?
更新
对于我们绑定的集合中的每个项目,我们在ItemDataBound
期间检查数据库以获取有关该项目的更多信息,例如语言等。这当前阻止我们在绑定数据之前过滤绑定数据
答案 0 :(得分: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();
所以预先应用所有过滤
这将减少数据库的往返次数,从而提高性能
答案 1 :(得分:2)
为什么不在绑定之前过滤数据源。所以假设你使用的是一些自定义对象:
myRepeater.DataSource=repository.getItems().Where(item=>item.Language==CurrentLanguage);
如果您不需要它们,请不要首先绑定它们。
<强>更新强>
如果可能的话,你应该从数据库中提前获取该信息。这些清单大吗?如果是这样,对列表中的每个项目按一次db将显示为性能问题。
答案 2 :(得分: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
}
答案 3 :(得分: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
中过滤没有任何问题。如果您正在进行任何类型的分页,则可能会出现问题,因为这会导致呈现不一致的页面大小。