Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repeater control - Cancel bind for specific item

Within a repeater control, is there a way of de-binding certain items before the page is rendered?

Currently we have a collection of items being bound to a repeater and if the item is not part of the current language, we hide the item.

I'm wanting to be able to do a count on the repeater and get a valid number back. A count that doesn't also include the hidden items.

Is it possible to de-bind specific items perhaps in the ItemDataBound event?

Update

For each item in the collection we're binding, we check the database during the ItemDataBound for further information about the item, such as language etc. This is currently stopping us from filtering the bound data before binding it.

like image 472
Jamie Dixon Avatar asked Feb 08 '10 14:02

Jamie Dixon


3 Answers

A more appropriate solution could be to filter the bound collection if there is no specific need in those hidden items. Something like

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

Update:

As for me I'd use this approach:

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

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

So all filtering is applied beforehand

This will reduce the number of round-trips to the database as well, which plays for better performance

like image 194
dh. Avatar answered Nov 09 '22 16:11

dh.


I agree with the others answers - the best solution (for both performance and code clarity) is to redesign the page so that you can filter invalid entries out before databinding.

Most data sources don't allow us to remove their items while ASP.NET is iterating them. For example, if you bind to a simple generic List<T>, and you remove an item while iterating it, the list will throw an InvalidOperationException.

In other cases, ASP.NET actually iterates a a copy of the data source. If you bind to a DataTable, ASP.NET uses a copy of the contents (the default DataView) rather than iterating the source rows themselves - you can remove items from the underlying data source while iterating, but it doesn't affect the databinding operation.

If filtering the items in advance really isn't an option, your current solution is fine: just hide the items! If you need to get the correct count on top of that, track the number of invalid items in your ItemDataBound handler and expose it as a page-level property:

if (IsInvalid(args.Item.DataItem)) {
    this.invalidItemCount++;
    // code to hide the current item
}
like image 2
Jeff Sternal Avatar answered Nov 09 '22 16:11

Jeff Sternal


Why not filter the datasource before binding. So assuming you are using some custom objects:

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

If you don't need them don't bind them in the first place.

Update

If it's at all possible you should probally pull that info from the DB upfront. Are these lists large? If so hitting the db once for each item in the list will show up as a performance problem.

like image 2
JoshBerke Avatar answered Nov 09 '22 17:11

JoshBerke