Can I use loops in repeater? Is it recommended?

2019-08-02 18:31发布

问题:

My datasource has an Rating dataItem contains an integer from 0 to 5. I'd like to print stars accordignly.

I'm trying to do it within Repeater control:

<b>Rating:</b>

<% for (int j = 1; j <= DataBinder.Eval(Container.DataItem, "Rating"); j++)
{  %>
<img src="App_Pics/fullstar.png" />
<% }
for (int j = 1; j <= 5 - DataBinder.Eval(Container.DataItem, "Rating"); j++)
{ %>
<img src="App_Pics/emptystar.png" />
<%} %>
  1. I get the error The name 'Container' does not exist in the current context. It is weird, because when I used <%# DataBinder.Eval(Container.DataItem, "Name")%> a line before, it worked great.
  2. Is it clever to include loops in my aspx page? I think it's not very convenient. What's my alternatives?
  3. What's that # means?

Thank you very much.

回答1:

The # indicates code to be executed when data-binding occurs (i.e. when DataBind() is called on the control or the page). The <%# %> syntax is the data-binding equivilent of <%= %> so unfortunately you can't just wrap your loop in <%# %> blocks and be done with it.

You can around this limitation by implementing a code-behind method and passing the rating to the method:

<%# GetStars(Convert.ToInt32(DataBinder.Eval(Container.DataItem, "Rating"))) %>

And then implement the method as:

protected string GetStars(int rating)
{
    string output = string.Empty;
    for (int j = 1; j <= rating; j++) output += "<img src=\"App_Pics/fullstar.png\" />";
    for (int j = 1; j <= 5 - rating; j++) output += "<img src=\"App_Pics/emptystar.png\" />";
    return output;
}


回答2:

The # indicates a databound item, which is why you're seeing the error you've mentioned; you're using DataBinding outside of it's context.

The best solution would be to convert your star rater into an external control (an ascx control). You can add a property called "Rating", assign it from your databound context, and do the looping within the star rater control.



回答3:

Point 2, you certainly can do it, and you'll find a few examples of it in tutorials and stuff. Personally I like to try and keep as much code as possible in the codebehind, but sometimes it's not worth it...



回答4:

I would not recommend using a loop that way. There are, of course, ways to put 5 images together like you need them with stars on or off, but another idea is to simply create 6 static images, with 0 to 5 stars turned on. 0star.jpg, 1star.jpg, etc. Then your "rating" value can be used simply to generate the appropriate filename.



回答5:

I'm not sure loops are such a great idea with a Repeater control. Better practise is to loop the DataSource itself (in the code-behind), so the Repeater only needs a single iteration to render the HTML.

If you need some composite HTML structure for display, I'd go with jvenema's solution and use another UserControl to render it.



回答6:

The best would be for me to have something like :

codebehind :

protected List<int> Stars = new List<int> { 1, 2, 3, 4, 5 };
protected int RankingStars = 3;

aspx :

<asp:Repeater runat=server ID=C_Rep_StarsFull DataSource=Stars >
    <ItemTemplate>
          <img src="App_Pics/fullstar.png" runat=server 
                visible=<%# RankingStars >= (int)Container.DataItem %>/>
    </ItemTemplate>
</asp:Repeater>
<asp:Repeater runat=server ID=C_Rep_StarsEmpty DataSource=Stars >
    <ItemTemplate>
          <img  src="App_Pics/emptystar.png" runat=server 
                visible=<%# RankingStars < (int)Container.DataItem %>/>
    </ItemTemplate>
</asp:Repeater>