tags:

views:

39

answers:

2

I have built a simple shopping cart. The problem is that the first time i try to add an item nothing happens. If i click the buy button a second time an item is added. What is the cause if this problem?

Thanx!

.aspx

<asp:Content ContentPlaceHolderID="main" runat="server">
White lily
<asp:Button ID="button" runat="server" OnClick="buy_Click" />
</asp:Content>

<asp:Content ContentPlaceHolderID="rightBar" runat="server">
    <UserControl:ShoppingCart id="shoppingCart" runat="server" />
</asp:Content>

.ascx

public partial class UserControls_ShoppingCart : System.Web.UI.UserControl
{
    private List<Flower> FlowerList 
    {
        get
        {
            List<Flower> tmp = Session["FlowerList"] as List<Flower>;
            if (tmp == null)
            {
                tmp = new List<Flower>();
            }
            return tmp;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
        {
            FillRepeater();
        }

    }

    public void ShoppingCart_ItemDataBound(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item != null)
        {
            Label itemLabel = e.Item.FindControl("itemLabel") as Label;
            Flower flower = e.Item.DataItem as Flower;
            if (flower != null)
            {
                itemLabel.Text = flower.getName(flower);
            }
        }
    }

    private void FillRepeater()
    {
        shoppingCartRepeater.DataSource = FlowerList;
        shoppingCartRepeater.DataBind();
    }

    public void AddFlower(Flower flower)
    {
        FlowerList.Add(flower);
        Session["FlowerList"] = FlowerList;
        FillRepeater();
    }
}
A: 

OK, I'm guessing here based on skimming the code, so I might be wrong but maybe the first time around it's not a postback and FillRepeater does not get called.

Gabriel
Was thinking the same thing but he calls FillRepeater in AddFlower. I think it has something to do with the weird FlowerList property/session object.
jamietre
Gabriel, i tryed to remove if (!Page.IsPostBack) but the problem remains.
Andy
I am surprised I'm not sure if this is the case, but when you assign a Session variable is it immediately available for reading? I think maybe not. So the first time you add a Flower, then assign it to the Session["FlowerList"], FillRepeater will not know about it - the property will return a new FlowerList. After the 2nd postback it will contain the value it got before, though. This would explain it. You should not use Session to keep values during a given page execution. Add a "get" property and store the object in a private object as well.
jamietre
+1  A: 

Pursuant to my comment on the first answer.. try this

 private List<Flower> FlowerList 
    {
        get
        {
             return(_FlowerList);
        }
        set
        {
            _FlowerList = value;
        }

    }
    protected List<Flower> _FlowerList = new FlowerList();
    protected void Page_Load(object sender, EventArgs e)
    {
       if (Session["FlowerList"]!= null) {
           FlowerList = (List<Flower>)Session["FlowerList"];
       }
        if (!Page.IsPostBack)
        {
            FillRepeater();
        }
    }

It should work with everything else the same. A better way would be to use ViewState though, and save the value of _FlowerList in SaveViewState()

jamietre
Big thank you jamietre, your solution worked fine. The only thing i needed to change was (FlowerList)Session["FlowerList"] to (List<Flower>)Session["FlowerList"]
Andy
Ah, the risks of writing (but not running) code. Fixed in the response, glad it helped.
jamietre
interesting, it's kinda the opposite of lazy loading creating the object everytime only to be stored in session when its not there. i suppose the 'inefficiency' is negligible here
Gabriel
@gabriel, i can't disagree with you, it was not well thought except to the extent of "will it work." It would be better to add logic in the "get" to check _FlowerList for a value first, if null then load the session value (if available), and finally create a new object if none of the above. Or I guess just check for null in the get and leave the Session in page load? Anyway... details...
jamietre
@jamietre, +1 I totally respect the 'get it to work' attitude.
Gabriel
Big thanx to all that helped me with this one!
Andy