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

Grid Performance Issues When All Rows in Edit Mode

3 Answers 89 Views
Grid
This is a migrated thread and some comments may be shown as answers.
tlp
Top achievements
Rank 1
tlp asked on 31 Jul 2012, 12:58 PM
Hello,

A grid was dynamically created with 2 Rad combobox controls and 14 Rad numeric controls as columns. As more rows are added to the grid control and placed in edit mode, the creation of the new rows on the grid become slower. Basically, when the grid gets to about 20 rows the time required to add the new row and place all rows into edit mode becomes unacceptable. Also, since the comboboxes are related, the time it takes to load items within the second combo box gets slower.

I realize that adding RAD controls to the grid and placing them in edit mode adds complexity to the creation of the page, especially when all rows are placed in edit mode. I would really like to get this resolved since our requirement is to be able to have all rows in edit mode and provide the capability to quickly enter data without a performance hit.

Provided is sample code of how the issue is created. Any help in resolving the performance issues would be appreciated. You will notice that when you click on the Add button and continue to add rows to the page, the process gets slower and slower.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default4.aspx.cs" Inherits="Default4" %>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<head runat="server">
    <title></title>
</head>
 
<body>
    <form id="form1" runat="server">   
    <div>
        <asp:Button ID="ButtonAdd" runat="server" Text="Add Row" OnClick="ButtonAdd_Click" />       
        <asp:placeholder ID="Placeholder1" runat="server"></asp:placeholder>
    </div>
    <telerik:RadScriptManager runat="server" ID="RadScriptManager1" />
    <telerik:RadAjaxManager runat="server" ID="RadAjaxManager1" />
    </form>
</body>
</html>


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
 
using Telerik.Web.UI;
 
public partial class Default4 : System.Web.UI.Page
{
 
    private List<ProjectItem> ProjectItemList
    {
        get
        {
            if (ViewState["ProjectItemList"] == null)
            {
 
                ProjectItem projectItem = new ProjectItem();
 
                List<ProjectItem> list = new List<ProjectItem>();
                list.Add(projectItem);
 
                ViewState["ProjectItemList"] = list;
            }
            return (List<ProjectItem>)ViewState["ProjectItemList"];
        }
 
        set { ViewState["ProjectItemList"] = value; }
    }
 
    private List<ProjectCode> ProjectCodeList
    {
        get
        {
            if (ViewState["ProjectCodeList"] == null)
            {
 
                List<ProjectCode> list = new List<ProjectCode>();
 
                list.Add(new ProjectCode("P1", "Project 1"));
                list.Add(new ProjectCode("P2", "Project 2"));
                list.Add(new ProjectCode("P3", "Project 3"));
                list.Add(new ProjectCode("P4", "Project 4"));
                list.Add(new ProjectCode("P5", "Project 5"));
                list.Add(new ProjectCode("P6", "Project 6"));
                list.Add(new ProjectCode("P7", "Project 7"));
 
                ViewState["ProjectCodeList"] = list;
            }
            return (List<ProjectCode>)ViewState["ProjectCodeList"];
        }
 
        set { ViewState["ProjectCodeList"] = value; }
    }
 
    private List<ChargeCode> ChargeCodeList
    {
        get
        {
            if (ViewState["ChargeCodeList"] == null)
            {
 
                List<ChargeCode> list = new List<ChargeCode>();
 
                list.Add(new ChargeCode("C1", "Charge Code A", "P1"));
                list.Add(new ChargeCode("C2", "Charge Code B", "P1"));
                list.Add(new ChargeCode("C3", "Charge Code C", "P1"));
                list.Add(new ChargeCode("C4", "Charge Code D", "P2"));
                list.Add(new ChargeCode("C5", "Charge Code E", "P2"));
                list.Add(new ChargeCode("C6", "Charge Code F", "P3"));
                list.Add(new ChargeCode("C7", "Charge Code G", "P3"));
                list.Add(new ChargeCode("C8", "Charge Code H", "P3"));
                list.Add(new ChargeCode("C9", "Charge Code I", "P4"));
                list.Add(new ChargeCode("C10", "Charge Code J", "P4"));
                list.Add(new ChargeCode("C11", "Charge Code K", "P5"));
                list.Add(new ChargeCode("C12", "Charge Code L", "P5"));
                list.Add(new ChargeCode("C13", "Charge Code M", "P6"));
                list.Add(new ChargeCode("C14", "Charge Code N", "P6"));
                list.Add(new ChargeCode("C15", "Charge Code O", "P7"));
                list.Add(new ChargeCode("C16", "Charge Code P", "P7"));
                list.Add(new ChargeCode("C17", "Charge Code Q", "P7"));
 
                ViewState["ChargeCodeList"] = list;
            }
            return (List<ChargeCode>)ViewState["ChargeCodeList"];
        }
 
        set { ViewState["ChargeCodeList"] = value; }
    }
 
    protected RadGrid Grid
    {
        get;
        set;
    }
 
    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
 
        this.InitializeGrid();
    }
 
 
    protected void Page_Load(object sender, EventArgs e)
    {
        InitializeAjaxManager();
 
        // Set grid items in edit mode.
        Grid.EditIndexes.Clear();
        for (int i = 0; i < ProjectItemList.Count; i++)
        {
            Grid.EditIndexes.Add(i);
        }
    }
 
 
    private void InitializeAjaxManager()
    {
        RadAjaxManager ajaxManager = RadAjaxManager.GetCurrent(Page);
 
        if (ajaxManager == null)
            return;
 
        ajaxManager.AjaxSettings.AddAjaxSetting(ButtonAdd, Grid);
        ajaxManager.AjaxSettings.AddAjaxSetting(Grid, Grid);
    }
 
 
    private void InitializeGrid()
    {
        GridBoundColumn boundColumn;
        GridNumericColumn numericColumn;
        GridDropDownColumn dropDownColumn;
 
        Grid = new RadGrid();
 
        // Setup required event handlers.
        Grid.NeedDataSource += new GridNeedDataSourceEventHandler(Grid_NeedDataSource);
        Grid.ItemCreated += new GridItemEventHandler(Grid_ItemCreated);
        Grid.ItemDataBound += new GridItemEventHandler(Grid_ItemDataBound);
                 
        Grid.ID = "GridProject";
        Grid.AllowSorting = false;
        Grid.AutoGenerateColumns = false;
        Grid.AllowMultiRowEdit = true;
        Grid.Width = Unit.Percentage(100);
         
        Grid.ClientSettings.Selecting.AllowRowSelect = false;       
                 
        Grid.MasterTableView.DataKeyNames = new string[] { "Id" };
        Grid.MasterTableView.Name = "MasterTableViewProject";
        Grid.MasterTableView.DataMember = "ProjectItem";
        Grid.MasterTableView.EditMode = GridEditMode.InPlace;       
 
        // Initialize the grid columns.
 
        boundColumn = new GridBoundColumn();
        Grid.MasterTableView.Columns.Add(boundColumn);
        boundColumn.Visible = false;
        boundColumn.UniqueName = "Id";
        boundColumn.DataField = "Id";
        boundColumn.HeaderText = "Id";
 
        dropDownColumn = new GridDropDownColumn();
        Grid.MasterTableView.Columns.Add(dropDownColumn);
        dropDownColumn.Visible = true;
        dropDownColumn.UniqueName = "ComboBoxProjectCode";
        dropDownColumn.DataField = "ProjectCode";
        dropDownColumn.HeaderText = "Project Code";
        dropDownColumn.HeaderStyle.Width = Unit.Pixel(200);
        dropDownColumn.ItemStyle.Width = Unit.Pixel(200);
        dropDownColumn.DropDownControlType = GridDropDownColumnControlType.RadComboBox;       
 
        dropDownColumn = new GridDropDownColumn();
        Grid.MasterTableView.Columns.Add(dropDownColumn);
        dropDownColumn.Visible = true;
        dropDownColumn.UniqueName = "ComboBoxChargeCode";
        dropDownColumn.DataField = "ChargeCode";
        dropDownColumn.HeaderText = "Charge Code";
        dropDownColumn.HeaderStyle.Width = Unit.Pixel(200);
        dropDownColumn.ItemStyle.Width = Unit.Pixel(200);
        dropDownColumn.DropDownControlType = GridDropDownColumnControlType.RadComboBox;
                 
        for (int i = 0; i < 14; i++)
        {
             
            numericColumn = new GridNumericColumn();
            Grid.MasterTableView.Columns.Add(numericColumn);
            numericColumn.Visible = true;
            numericColumn.UniqueName = "D" + i.ToString();
            numericColumn.DataField = "D" + i.ToString();
            numericColumn.HeaderText = "D" + i.ToString();
            numericColumn.DecimalDigits = 2;
            numericColumn.HeaderStyle.Width = Unit.Pixel(50);
            numericColumn.HeaderStyle.HorizontalAlign = HorizontalAlign.Right;
            numericColumn.ItemStyle.Width = Unit.Pixel(50);
            numericColumn.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
            numericColumn.ReadOnly = false;
             
        }       
 
        Placeholder1.Controls.Add(this.Grid);
    }   
    
    void Grid_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
    {
        Grid.DataSource = ProjectItemList;
    }   
 
    void Grid_ItemCreated(object sender, GridItemEventArgs e)
    {
        if ((e.Item.IsInEditMode) && (e.Item is GridDataItem))
        {
 
            GridDataItem gridDataItem = e.Item as GridDataItem;
 
            RadComboBox comboBoxProjectCode;
            comboBoxProjectCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxProjectCode")).ComboBoxControl;
            comboBoxProjectCode.EmptyMessage = "Select Project Code";
            comboBoxProjectCode.AutoPostBack = true;
            comboBoxProjectCode.EnableLoadOnDemand = true;
            comboBoxProjectCode.MarkFirstMatch = true;
            comboBoxProjectCode.Filter = RadComboBoxFilter.StartsWith;
            comboBoxProjectCode.Width = Unit.Pixel(200);
            comboBoxProjectCode.DropDownWidth = Unit.Pixel(300);
 
            comboBoxProjectCode.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(comboBoxProjectCode_SelectedIndexChanged);
            comboBoxProjectCode.ItemsRequested += new RadComboBoxItemsRequestedEventHandler(comboBoxProjectCode_ItemsRequested);
             
            RadComboBox comboBoxChargeCode;
            comboBoxChargeCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxChargeCode")).ComboBoxControl;           
            comboBoxChargeCode.Width = Unit.Pixel(200);
            comboBoxChargeCode.EmptyMessage = "Select Charge Code";
            comboBoxChargeCode.EnableLoadOnDemand = true;
            comboBoxChargeCode.ItemsRequested += new RadComboBoxItemsRequestedEventHandler(comboBoxChargeCode_ItemsRequested);
 
 
            // Set data values for the combo box.
            if (gridDataItem.DataItem != null)
            {
                if (!string.IsNullOrEmpty(((ProjectItem)gridDataItem.DataItem).ProjectCode))
                {
                    comboBoxProjectCode.Items.Add(new RadComboBoxItem(((ProjectItem)gridDataItem.DataItem).ProjectName, ((ProjectItem)gridDataItem.DataItem).ProjectCode));
                }
 
                if (!string.IsNullOrEmpty(((ProjectItem)gridDataItem.DataItem).ChargeCodeName))
                {
                    comboBoxChargeCode.Items.Add(new RadComboBoxItem(((ProjectItem)gridDataItem.DataItem).ChargeCodeName, ((ProjectItem)gridDataItem.DataItem).ChargeCode));
                }
            }
 
        }
    }
 
    void Grid_ItemDataBound(object sender, GridItemEventArgs e)
    {
        if ((e.Item.IsInEditMode) && (e.Item is GridDataItem))
        {
             
            GridDataItem gridDataItem = e.Item as GridDataItem;
            GridNumericColumnEditor columnEditor;           
 
            for (int i = 0; i < 14; i++)
            {               
                columnEditor = (GridNumericColumnEditor)gridDataItem.EditManager.GetColumnEditor("D" + i.ToString());
                columnEditor.NumericTextBox.Width = Unit.Percentage(100);
                columnEditor.NumericTextBox.EnabledStyle.HorizontalAlign = HorizontalAlign.Right;
                columnEditor.NumericTextBox.MinValue = 0;
                columnEditor.NumericTextBox.NumberFormat.DecimalDigits = 2;
                columnEditor.NumericTextBox.NumberFormat.KeepTrailingZerosOnFocus = true;
                columnEditor.NumericTextBox.NumberFormat.AllowRounding = true;
            }
        }
    }
    
    void comboBoxProjectCode_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
    {       
        GridDataItem gridDataItem = (sender as RadComboBox).NamingContainer as GridDataItem;
 
        RadComboBox comboBoxChargeCode;
        comboBoxChargeCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxChargeCode")).ComboBoxControl;
        if (comboBoxChargeCode != null)
        {           
            comboBoxChargeCode.Text = string.Empty;
            comboBoxChargeCode.SelectedValue = string.Empty;
        }
    }
 
    void comboBoxProjectCode_ItemsRequested(object sender, RadComboBoxItemsRequestedEventArgs e)
    {
        RadComboBox comboBoxProjectCode = sender as RadComboBox;
 
        comboBoxProjectCode.Items.Clear();
        foreach (ProjectCode projectCode in ProjectCodeList)
        {
            comboBoxProjectCode.Items.Add(new RadComboBoxItem(projectCode.Name, projectCode.Code));
        }
    }
 
    void comboBoxChargeCode_ItemsRequested(object sender, RadComboBoxItemsRequestedEventArgs e)
    {
        RadComboBox comboBoxChargeCode = sender as RadComboBox;
        GridDataItem gridDataItem = comboBoxChargeCode.NamingContainer as GridDataItem;
 
        RadComboBox comboBoxProjectCode;
        comboBoxProjectCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxProjectCode")).ComboBoxControl;
 
        List<ChargeCode> list = ChargeCodeList.Where(code => code.ProjectCode == comboBoxProjectCode.SelectedValue).ToList();
 
        comboBoxChargeCode.Items.Clear();
        foreach (ChargeCode chargeCode in list)
        {
            comboBoxChargeCode.Items.Add(new RadComboBoxItem(chargeCode.Name, chargeCode.Code));
        }
    }
 
 
    protected void ButtonAdd_Click(object sender, EventArgs e)
    {       
 
        for (int i = 0; i < Grid.MasterTableView.Items.Count; i++)
        {
            GridDataItem gridDataItem = Grid.MasterTableView.Items[i];
 
            if (!Grid.MasterTableView.Items[i].IsInEditMode)
                continue;
 
            // Persist existing entered data.
            RadComboBox comboBoxProjectCode;
            comboBoxProjectCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxProjectCode")).ComboBoxControl;
            ProjectItemList[i].ProjectCode = comboBoxProjectCode.SelectedValue;
            ProjectItemList[i].ProjectName = comboBoxProjectCode.Text;
 
            RadComboBox comboBoxChargeCode;
            comboBoxChargeCode = ((GridDropDownListColumnEditor)gridDataItem.EditManager.GetColumnEditor("ComboBoxChargeCode")).ComboBoxControl;
            ProjectItemList[i].ChargeCode = comboBoxChargeCode.SelectedValue;
            ProjectItemList[i].ChargeCodeName = comboBoxChargeCode.Text;
 
            GridNumericColumnEditor columnEditor;
            for (int j = 0; j < 14; j++)
            {
                columnEditor = (GridNumericColumnEditor)gridDataItem.EditManager.GetColumnEditor("D" + j.ToString());
                ProjectItemList[i].DataList[j] = (decimal)columnEditor.NumericTextBox.Value;
            }
        }
 
 
        ProjectItem projectItem = new ProjectItem();
        ProjectItemList.Add(projectItem);
 
        Grid.EditIndexes.Clear();
        for (int i = 0; i < ProjectItemList.Count; i++)
        {
            Grid.EditIndexes.Add(i);
        }
 
        Grid.Rebind();
    }
 
    [Serializable]
    private class ProjectItem
    {
        public ProjectItem()
        {  
            DataList = new List<decimal>();
 
            for (int i = 0; i < 14; i++)
            {
                DataList.Add(0);
            }
        }
 
        public long Id
        {
            get;
            set;
        }
 
        public string ProjectCode
        {
            get;
            set;
        }
 
        public string ProjectName
        {
            get;
            set;
        }
 
        public string ChargeCode
        {
            get;
            set;
        }
 
        public string ChargeCodeName
        {
            get;
            set;
        }
 
        public List<decimal> DataList
        {
            get;
            set;
        }
 
        public decimal D0
        {
            get { return DataList[0]; }
        }
 
        public decimal D1
        {
            get { return DataList[1]; }
        }
 
        public decimal D2
        {
            get { return DataList[2]; }
        }
 
        public decimal D3
        {
            get { return DataList[3]; }
        }
 
        public decimal D4
        {
            get { return DataList[4]; }
        }
 
        public decimal D5
        {
            get { return DataList[5]; }
        }
 
        public decimal D6
        {
            get { return DataList[6]; }
        }
 
        public decimal D7
        {
            get { return DataList[7]; }
        }
 
        public decimal D8
        {
            get { return DataList[8]; }
        }
 
        public decimal D9
        {
            get { return DataList[9]; }
        }
 
        public decimal D10
        {
            get { return DataList[10]; }
        }
 
        public decimal D11
        {
            get { return DataList[11]; }
        }
 
        public decimal D12
        {
            get { return DataList[12]; }
        }
 
        public decimal D13
        {
            get { return DataList[13]; }
        }
    }
 
    [Serializable]
    private class ProjectCode
    {
 
        public ProjectCode(string code, string name)
        {
            Code = code;
            Name = name;
        }
 
        public string Code
        {
            get;
            set;
        }
 
        public string Name
        {
            get;
            set;
        }
    }
 
    [Serializable]
    private class ChargeCode
    {
 
        public ChargeCode(string code, string name, string projectCode)
        {
            Code = code;
            Name = name;
            ProjectCode = projectCode;
        }
 
        public string Code
        {
            get;
            set;
        }
 
        public string Name
        {
            get;
            set;
        }
 
        public string ProjectCode
        {
            get;
            set;
        }
    }
}

3 Answers, 1 is accepted

Sort by
0
Pavlina
Telerik team
answered on 03 Aug 2012, 01:36 PM
Hi Tony,

You can refer to the forum thread below for more information on this subject:
http://www.telerik.com/community/forums/aspnet-ajax/grid/very-low-performance-on-databing-using-an-excel-like-grid-implementation.aspx


All the best,
Pavlina
the Telerik team
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 their blog feed now.
0
tlp
Top achievements
Rank 1
answered on 03 Aug 2012, 02:20 PM
Hello Pavlina,

I understand that the page is loading numerous controls due to the excel-like layout and I already tried some of the suggestions that were mentioned in the form thread. At this point, I still have not been satisfied with the performance. I also changed the numeric controls to textbox controls (using RadInputManager) and found that the performance was still an issue.

I'm interested in your last post within the form thread that you provided. You indicated that if a working sample was provided, you would get back with the findings. I'm interested in the findings, if any were provided.

Also, I provided a sample to see if anyone at telerik can offer a possible solution or point me in the right direction. Seeing that there are several form threads regarding an excel-like grid, why not just provide the capability within the existing grid with the utilization of "lightweight" controls.

I find that placing 20-40 rows in edit mode should not bloat the page size to the point where the loading time is unacceptable. From my perspective, why even offer the multi-row edit if this is the case.

Thanks,

Tony


0
Pavlina
Telerik team
answered on 08 Aug 2012, 10:22 PM
Hello,

To optimize the performance in your case I suggest you to reducing the number of visible column as much as possible (either hiding some of the columns or removing them completely and extracting their values on the client using key values)
Also we have many optimization techniques for such a scenarios and I am sure some of them will be of great help for your project . The info below summarize the most important performance info we already have in our documentation resources: :
http://www.telerik.com/products/aspnet-ajax/resources/top-performance.aspx
http://www.telerik.com/help/aspnet-ajax/grdviewstatereductiontechniques.html
http://www.telerik.com/help/aspnet-ajax/grdsavinggridviewstateinsession.html
http://www.telerik.com/help/aspnet-ajax/radinputmanager_performance.html

If you need further assistance, do not hesitate to contact us again.

Kind regards,
Pavlina
the Telerik team
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 their blog feed now.
Tags
Grid
Asked by
tlp
Top achievements
Rank 1
Answers by
Pavlina
Telerik team
tlp
Top achievements
Rank 1
Share this question
or