This is a migrated thread and some comments may be shown as answers.

Telerik radgrid paging in webshop, breaks when changing product amount on last page

3 Answers 68 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Magnus
Top achievements
Rank 1
Magnus asked on 23 Sep 2013, 09:54 AM

I'm having some problems with one of our webshops. A Telerik radgrid works as the cart and lists all products currently in the cart. The paging on the Radgrid correctly splits the cart view into different pages. The problem occurs when one manually tries to change the amount of a product, but only if the product is on the LAST page of the radgrid and only if the number of products are less than the page size limit.


I have figured it out as much as the radgrid believes there are always an even amount of products, based on the radgrid's page size.

The crash occurs in the tbQuantity_TextChanged event handler, more specific when var shopItemID = Convert.ToInt32(item.GetDataKeyValue("ID")); is called for an item that doesn't exist on this page, but on another page.

The exception is

System.ArgumentOutOfRangeException was unhandled by user code
  Message=Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index

 
Gridview code

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="ShopItems.ascx.cs" Inherits="Litho.Framework.Web.Modules.Shop.ShopItems" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
 
<telerik:RadGrid
    ID="gvCartItems"
    runat="server"
    AutoGenerateColumns="False"
    AllowPaging="True"
    PageSize="5"
    Skin="Default"
    GridLines="None"
    AllowFilteringByColumn="False"
    AllowSorting="True"
    ShowFooter="True"
    OnNeedDataSource="gvCartItems_NeedDataSource"
    OnItemCreated="gvCartItems_ItemCreated"
    OnItemDataBound="gvCartItems_ItemDataBound"
    OnDeleteCommand="gvCartItems_DeleteCommand">
 
    <MasterTableView Width="100%" NoMasterRecordsText="Inga artiklar" ShowHeadersWhenNoRecords="false" DataKeyNames="ID">
        <Columns>
            <telerik:GridButtonColumn ButtonType="ImageButton" CommandName="Delete" Text="Radera" UniqueName="DeleteColumn" HeaderStyle-Width="20" />
            <telerik:GridTemplateColumn HeaderText="Antal" HeaderStyle-Width="110px" DataField="Quantity" UniqueName="Quantity" Aggregate="Sum" FooterText="Totalt antal: ">
                <ItemTemplate>
                    <telerik:RadNumericTextBox
                        ID="tbQuantity"
                        runat="server"
                        AutoPostBack="true"
                        Width="70px"
                        MinValue="1"
                        Visible="false"
                        ShowSpinButtons="true"
                        IncrementSettings-InterceptArrowKeys="false"
                        NumberFormat-GroupSizes="9"
                        NumberFormat-DecimalDigits="0"
                        IncrementSettings-InterceptMouseWheel="true"
                        NumberFormat-AllowRounding="False"
                        OnTextChanged="tbQuantity_TextChanged">
 
                        <EnabledStyle HorizontalAlign="Right" />
 
                    </telerik:RadNumericTextBox>
                        <telerik:RadComboBox ID="ddlQuantity" DataTextField="Quantity" DataValueField="Quantity" Visible="false" runat="server" Width="50px" AutoPostBack="true" OnSelectedIndexChanged="ddlQuantity_SelectedIndexChanged" />
                </ItemTemplate>
            </telerik:GridTemplateColumn>
 
 
            <telerik:GridBoundColumn HeaderText="Artnr" ReadOnly="True" DataField="ArticleNumber" UniqueName="ArticleNumber" HeaderStyle-Width="80" />
 
            <telerik:GridTemplateColumn  HeaderText="Artikel" UniqueName="Title" ShowFilterIcon="false">
                <ItemTemplate>
                    <asp:HyperLink ID="hlTitle" runat="server" />
                </ItemTemplate>
            </telerik:GridTemplateColumn>
 
            <telerik:GridTemplateColumn HeaderText="a`pris" UniqueName="Price" ShowFilterIcon="false">
                <ItemTemplate>
                    <asp:Label ID="lblUnitprice" runat="server" />
                </ItemTemplate>
            </telerik:GridTemplateColumn>
 
            <telerik:GridTemplateColumn HeaderText="Totalpris" UniqueName="Totalprice" ShowFilterIcon="false">
                <ItemTemplate>
                    <asp:Label ID="lblTotalPrice" runat="server" />
                </ItemTemplate>
            </telerik:GridTemplateColumn>
 
        </Columns>
    </MasterTableView>
 
    <FooterStyle Font-Bold="true" BackColor="#e6e6e6" />
 
    <PagerStyle Mode="NextPrevAndNumeric" />
 
    <FilterMenu EnableTheming="True">
        <CollapseAnimation Duration="200" Type="OutQuint" />
    </FilterMenu>
 
</telerik:RadGrid>
 
<asp:PlaceHolder ID="phItemSummary" runat="server" />

Code behind

using System;
using System.Collections.Generic;
using System.Web.UI;
using System.Web.UI.WebControls;
using Litho.Framework.BusinessLayer;
using Litho.Framework.BusinessLayer.Base;
using Litho.Framework.BusinessLayer.Base.Settings;
using Litho.Framework.BusinessLayer.Modules.Shop;
using Litho.Framework.PresentationLayer;
using Litho.Framework.ServiceLayer;
using Telerik.Web.UI;
 
namespace Litho.Framework.Web.Modules.Shop
{
    public partial class ShopItems : UserControl
    {
        IShopItemHolder _shopItemHolder = null;
        bool _readMode = true;
        SessionHelper _sessionHelper = new SessionHelper();
 
        #region Public methods
 
        public void LoadItems(IShopItemHolder shopItemHolder, bool readMode)
        {
            _shopItemHolder = shopItemHolder;
            _readMode = readMode;
 
            gvCartItems.Rebind();
 
            loadItemsSummary();
        }
 
        private void loadItemsSummary()
        {
            phItemSummary.Controls.Clear();
 
            var ucItemSummary = (ShopItemsSummary)Page.LoadControl("~/Modules/Shop/ShopItemsSummary.ascx");
            ucItemSummary.LoadItemSummary(_shopItemHolder);
 
            phItemSummary.Controls.Add(ucItemSummary);
        }
 
        #endregion
 
        #region Events
 
        protected void gvCartItems_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
        {
            gvCartItems.DataSource = _shopItemHolder.Items;
        }
 
        protected void gvCartItems_ItemCreated(object sender, GridItemEventArgs e)
        {
            if (e.Item is GridDataItem)
            {
                var item = (GridDataItem)e.Item;
                var btnDelete = (ImageButton)item["DeleteColumn"].Controls[0];
 
                btnDelete.ImageUrl = string.Format("~/Base/Themes/{0}/Images/Icons16x16/iconDelete.png", SettingsManager.GetGlobalSettings().AdminTheme);
                btnDelete.Visible = !_readMode;
            }
        }
 
        protected void gvCartItems_ItemDataBound(object sender, GridItemEventArgs e)
        {
            if (e.Item is GridDataItem)
            {
                var shopItem = (IShopItem)e.Item.DataItem;
 
                var hlTitle = (HyperLink)e.Item.FindControl("hlTitle");
                var lblUnitPrice = (Label)e.Item.FindControl("lblUnitprice");
                var lblTotalPrice = (Label)e.Item.FindControl("lblTotalPrice");
 
                if (!shopItem.IsExternal)
                {
                    var tbQuantity = (RadNumericTextBox)e.Item.FindControl("tbQuantity");
                    tbQuantity.ShowSpinButtons = !_readMode;
                    tbQuantity.Text = shopItem.Quantity.ToString();
                    tbQuantity.Visible = true;
                    tbQuantity.Enabled = !_readMode;
                }
                else
                {
                    if (!_readMode)
                    {
                        var ddlQuantity = (RadComboBox)e.Item.FindControl("ddlQuantity");
                        ddlQuantity.DataSource = shopItem.PriceCollection;
                        ddlQuantity.DataBind();
                        ddlQuantity.SelectedValue = shopItem.Quantity.ToString();
                        ddlQuantity.Visible = true;
                    }
                }
 
                if (!shopItem.IsExternal)
                {
                    var parameters = new Dictionary<string, string>();
                    parameters.Add(KeyMaster.RequestParamsNames.Modules.Shop.PRODUCT_ID, shopItem.ID.ToString());
 
                    hlTitle.NavigateUrl = new FWContent().GetContentUrl(ModuleIDConstant.SHOP, ContentIDConstant.Shop.PRODUCT_VIEW, parameters);
                }
 
                hlTitle.Text = shopItem.Title;
 
                lblUnitPrice.Text = shopItem.Price.ToString("0.00") + " SEK";
                lblTotalPrice.Text = shopItem.GetCost(false).ToString("0.00") + " SEK";
            }
        }
 
        protected void tbQuantity_TextChanged(object sender, EventArgs e)
        {
            if (!_readMode)
            {
                RadNumericTextBox tbQuantity;
 
                foreach (GridDataItem item in gvCartItems.Items)
                {
                    if (item is GridDataItem)
                    {
                        tbQuantity = item.FindControl("tbQuantity") as RadNumericTextBox;
 
                        var shopItemID = Convert.ToInt32(item.GetDataKeyValue("ID"));
                        var shopItem = _sessionHelper.CurrentCart.CartItems.Find(x => x.ID == shopItemID);
 
                        if (!shopItem.IsExternal)
                        {
                            _sessionHelper.CurrentCart.CartItems.Find(x => x.ID == shopItemID).Quantity = Convert.ToInt32(tbQuantity.Text);
                            _sessionHelper.CurrentCart.CartItems.Find(x => x.ID == shopItemID).TotalPrice = _sessionHelper.CurrentCart.GetItemCost(shopItemID, false);
                            _shopItemHolder = _sessionHelper.CurrentCart;
                        }
                    }
                }
 
                loadItemsSummary();
                gvCartItems.Rebind();
            }
        }
 
        protected void gvCartItems_DeleteCommand(object source, GridCommandEventArgs e)
        {
            if (!_readMode)
            {
                var cartItemID = (int)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ID"];
                _sessionHelper.CurrentCart.DeleteItem(cartItemID);
                _shopItemHolder = _sessionHelper.CurrentCart;
 
                if (_sessionHelper.CurrentCart.Items.Count == 0)
                {
                    Response.Redirect(new FWContent().GetContentUrl(ModuleIDConstant.SHOP, ContentIDConstant.Shop.CART));
                }
                else
                {
                    gvCartItems.Rebind();
                    loadItemsSummary();
                }
            }
        }
 
        protected void ddlQuantity_SelectedIndexChanged(object sender, EventArgs e)
        {
            RadComboBox ddlQuantity;
 
            foreach (GridDataItem item in gvCartItems.Items)
            {
                if (item is GridDataItem)
                {
                    ddlQuantity = item.FindControl("ddlQuantity") as RadComboBox;
 
                    var cartItemID = Convert.ToInt32(item.GetDataKeyValue("ID"));
                    var cartItem = _sessionHelper.CurrentCart.CartItems.Find(x => x.ID == cartItemID);
 
                    if (cartItem.IsExternal)
                    {
                        cartItem.Quantity = Convert.ToInt32(ddlQuantity.Text);
                        cartItem.TotalPrice = getProductPrice(cartItem);
                    }
                }
            }
 
            loadItemsSummary();
 
            gvCartItems.Rebind();
        }
 
        #endregion
 
        private double getProductPrice(CartItem cartitem)
        {
            foreach (var price in cartitem.PriceCollection)
            {
                if (price.Quantity == cartitem.Quantity)
                {
                    return price.Price;
                }
            }
 
            throw new Exception(); // todo lägg till customexception
        }
    }
}

I've been trying to work something out with custom paging, but no luck so far, so I'm still using this code, only changed PageSize to 100 so the shop won't crash that easily. ;)

Thanks in advance!

3 Answers, 1 is accepted

Sort by
0
Magnus
Top achievements
Rank 1
answered on 24 Sep 2013, 01:33 PM
No ideas anyone?
If I did I miss something in my question, feel free to correct me and I will add the missing information.

Thanks!
0
Accepted
Eyup
Telerik team
answered on 26 Sep 2013, 10:32 AM
Hello Magnus,

You do not have to unnecessarily traverse all of the grid items. It is possible to access the corresponding item using the following approach:
protected void tbQuantity_TextChanged(object sender, EventArgs e)
{
    RadNumericTextBox numBox = (RadNumericTextBox)sender;
    GridDataItem dataItem = (GridDataItem)numBox.NamingContainer;
    int recordID = (int)dataItem.GetDataKeyValue("OrderID");
}

Hope this helps.

Regards,
Eyup
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0
Magnus
Top achievements
Rank 1
answered on 10 Oct 2013, 07:55 AM
Hello Eyup!
Sorry for late answer, but I haven't had the time to test this until now.

I was not aware of the fact that you could use this approach, thank you very much!
It appears to be working just the way I wanted. :)

Regards,
Magnus
Tags
Grid
Asked by
Magnus
Top achievements
Rank 1
Answers by
Magnus
Top achievements
Rank 1
Eyup
Telerik team
Share this question
or