1

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.

iTayb
  • 12,373
  • 24
  • 81
  • 135
  • Really two different problems. Problem A relates to the nuances of when how DataBinder.Eval works. Problem B is more succinctly stated as "should I nest loops". Problem A is the real problem here for you I think. – Russell Steen Mar 30 '10 at 14:18

6 Answers6

5

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;
}
Chris Van Opstal
  • 36,423
  • 9
  • 73
  • 90
  • Actually, I liked your way the best. thank you. BTW, is there any difference between output = "" and output = string.Empty? – iTayb Mar 30 '10 at 14:25
  • 1
    @iTayb, string.Empty is a preferred method of designating an empty string value, but not everybody agrees. See: http://stackoverflow.com/questions/263191/in-c-should-i-use-string-empty-or-string-empty-or – Anthony Pegram Mar 30 '10 at 14:26
  • 1
    There's no practical different between "" and string.Empty. The only reason I use it is to demonstrate my intent (i.e. I meant to create an empty string). – Chris Van Opstal Mar 30 '10 at 14:29
  • 1
    @sr pt: Using a StringBuilder is actually slower in this case. I just ran the loop above and a variant using StringBuilder a million times and found the StringBuilder to be about 18% slower. Of course each loop takes about 0.0007MS so I've just wasted five minutes of my life in micro-optimization theatre. Argg. Just wanted to make the point that using StringBuilder isn't necessarily a protip. It depends. – Chris Van Opstal Mar 30 '10 at 15:45
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.

Jerod Venema
  • 44,124
  • 5
  • 66
  • 109
1

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...

Martin Milan
  • 6,346
  • 2
  • 32
  • 44
1

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.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
0

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.

Prutswonder
  • 9,894
  • 3
  • 27
  • 39
0

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>
Arthis
  • 2,283
  • 21
  • 32