data binding on a hierarchical grid

3 posts, 0 answers
  1. Steve Bough
    Steve Bough avatar
    16 posts
    Member since:
    Jul 2007

    Posted 17 Jun 2008 Link to this post

    I'm having a bit of a problem with data binding on a hierarchical grid. I think I may have painted myself into a corner a bit by some of the choices I made along the way, but I'm hoping you guys can either tell me how to make this work or propose a different way of implementing it.
    The basic problem I have is that the data objects I'm using are very complex and don't really fit into the normal mechanisms for data binding since they consist of field collections which vary from object to object (so I can't use accessor binding), and are of complex types (so I can't  use data sets directly).
    The way I got around this was to use Template columns which accessed the objects directly from the source. Unfortunately when I use them in a hierarchical grid I'm running into problems with the fact that only the expanded detail table gets rebound.
    In a previous post you guys pointed out that I need to recreate the control structure for the view state to be bound into it, which worked fine for simple examples. In my real life sample however I actually don't know how many controls I need to create without having the data available, which means that all the other rows on the grid disappear.
    Ideally from my point of view I'd turn off the view state altogether and rebuild the entire grid every postback, but when I tried that it forgets which detail tables have been opened.
    So, is there any way to force a data bind on all expanded rows? Or alternatively is there a way to turn off view state while maintaining  the detail table expansion state? Or am I on completely the wrong track with what I'm doing and there's a much easier way to do it?
    I've knocked up a sample which pretty much does all the things I am doing for real, including the use of a hidden row count to associate with the real data set.
    Hopefully this makes some sense :)

    using System; 
    using System.Collections.Generic; 
    using System.Data; 
    using System.Web.UI; 
    using System.Web.UI.WebControls; 
    using Telerik.WebControls; 
     
    namespace GridTest1.Hierarchy 
        public partial class HierarchyComplex : Page 
        { 
            private RadGrid RadGrid1; 
     
            private List<DataItem> data; 
     
            protected override void OnInit(EventArgs e) 
            { 
                RadGrid1 = new RadGrid(); 
                SetupGrid(); 
                SetupGridColumns(); 
                form1.Controls.Add(RadGrid1); 
            } 
            protected void Page_Load(object sender, EventArgs e) 
            { 
                if (!IsPostBack) 
                { 
                    RadGrid1.DataSource = MakeDataSet(); 
                } 
            } 
     
            private void SetupGrid() 
            { 
                RadGrid1.EnableViewState = true
                RadGrid1.MasterTableView.EnableColumnsViewState = false
                RadGrid1.PageSize = 30
                RadGrid1.AllowPaging = true
                RadGrid1.AllowSorting = true
                RadGrid1.AutoGenerateColumns = false
                RadGrid1.ID = "Parent"
     
                RadGrid1.MasterTableView.Name = "Table1"
                RadGrid1.MasterTableView.ID = "Table1"
     
                RadGrid1.PagerStyle.AlwaysVisible = true
                RadGrid1.PagerStyle.Mode = GridPagerMode.NextPrevNumericAndAdvanced; 
                RadGrid1.PagerStyle.Position = GridPagerPosition.TopAndBottom; 
     
                //RadGrid1.ItemDataBound += BindTelericGridRow; 
                RadGrid1.DetailTableDataBind += grid_DetailTableDataBind; 
                RadGrid1.NeedDataSource += grid_NeedDataSource; 
            } 
            private void SetupGridColumns() 
            { 
                MakeData(); 
                AddTemplateColumn(RadGrid1.MasterTableView, "Column1"); 
     
                GridTableView childView = new GridTableView(RadGrid1, true); 
                RadGrid1.MasterTableView.DataKeyNames = new string[] { "Column1" }; 
     
                childView.Columns.Clear(); 
                AddTemplateColumn(childView, "Column1"); 
                AddTemplateColumn(childView, "Column2"); 
                AddTemplateColumn(childView, "RowNumber").Visible = false
                childView.Name = "Table2"
                childView.AllowPaging = false
                childView.AllowFilteringByColumn = false
                childView.EnableColumnsViewState = false
                childView.DataMember = "Table2"
     
                childView.DataKeyNames = new string[] { "Column1" }; 
                GridRelationFields rel = new GridRelationFields(); 
                rel.DetailKeyField = "Column1"
                rel.MasterKeyField = "Column1"
                childView.ParentTableRelation.Add(rel); 
     
                RadGrid1.MasterTableView.DetailTables.Clear(); 
                RadGrid1.MasterTableView.DetailTables.Add(childView); 
            } 
     
            void grid_NeedDataSource(object source, GridNeedDataSourceEventArgs e) 
            { 
                RadGrid grid = source as RadGrid; 
                if (!e.IsFromDetailTable) 
                    grid.DataSource = MakeDataSet(); 
            } 
            private GridTemplateColumn AddTemplateColumn(GridTableView view, string columnName) 
            { 
     
                GridTemplateColumn template = new GridTemplateColumn(); 
                ColumnTemplate cTemplate = new ColumnTemplate(columnName, data); 
                template.ItemTemplate = cTemplate
     
                template.HeaderText = columnName
                template.UniqueName = columnName
                template.DataField = columnName
                template.DataType = typeof(string); 
                view.Columns.Add(template); 
                return template; 
            } 
            private void grid_DetailTableDataBind(object source, GridDetailTableDataBindEventArgs e) 
            { 
                DataSet data = MakeDataSet(); 
                DataTable table = data.Tables[e.DetailTableView.DataMember]; 
                e.DetailTableView.DataSource = table
            } 
     
            public List<DataItem> MakeData() 
            { 
                data = new List<DataItem>(); 
                int parentCount = 5
                int childCount = 5
                for (int i = 0; i < parentCount; ++i) 
                { 
                    for (int j = 0; j < childCount; j++) 
                    { 
                        DataItem item = new DataItem(i, i * parentCount + j, (j % 3) + 1); 
                        data.Add(item); 
                    } 
                } 
                return data; 
            } 
     
            private DataSet MakeDataSet() 
            { 
                DataSet dataSet = new DataSet("DataSet"); 
     
                DataTable table = new DataTable("Table1"); 
                table.Columns.Add(new DataColumn("Column1", typeof(string))); 
                dataSet.Tables.Add(table); 
                MakeData(); 
                int parentId = -1; 
                foreach (DataItem item in data) 
                { 
                    if (item.ParentId != parentId) 
                    { 
                        DataRow row = table.NewRow(); 
                        row["Column1"] = item.ParentId; 
                        table.Rows.Add(row); 
                        parentId = item.ParentId; 
                    } 
                } 
     
                table = new DataTable("Table2"); 
                table.Columns.Add(new DataColumn("Column1", typeof(string))); 
                table.Columns.Add(new DataColumn("Column2", typeof(string))); 
                table.Columns.Add(new DataColumn("RowNumber", typeof(int))); 
                dataSet.Tables.Add(table); 
                int rowCount = 0
                foreach (DataItem item in data) 
                { 
                    DataRow row = table.NewRow(); 
                    row["Column1"] = item.ParentId; 
                    row["Column2"] = item.Id; 
                    row["RowNumber"] = rowCount++; 
                    table.Rows.Add(row); 
                } 
     
                return dataSet; 
            } 
     
            public class ColumnTemplate : ITemplate 
            { 
                private readonly string columnName; 
                private readonly List<DataItem> dataSet; 
                public ColumnTemplate(string columnName, List<DataItem> dataSet) 
                { 
                    this.columnName = columnName; 
                    this.dataSet = dataSet; 
                } 
     
                #region ITemplate Members 
     
                public void InstantiateIn(Control container) 
                { 
                    ColumnControl column = new ColumnControl(columnName, dataSet); 
                    column.ID = "Column" + columnName; 
                    container.Controls.Add(column); 
                } 
     
                #endregion 
            } 
     
            public class DataItem 
            { 
                private readonly int parentId; 
                private readonly int id; 
                private readonly int labelCount; 
     
                public DataItem(int parentId, int id, int labelCount) 
                { 
                    this.parentId = parentId; 
                    this.id = id; 
                    this.labelCount = labelCount; 
                } 
     
                public int LabelCount 
                { 
                    get { return labelCount; } 
                } 
                public int Id 
                { 
                    get { return id; } 
                } 
                public int ParentId 
                { 
                    get { return parentId; } 
                } 
                public List<Label> Labels 
                { 
                    get 
                    { 
                        List<Label> labels = new List<Label>(); 
                        for (int i = 0; i < labelCount; ++i) 
                        { 
                            Label l = new Label(); 
                            l.Text = i.ToString(); 
                            labels.Add(l); 
                        } 
     
                        return labels; 
                    } 
                } 
            } 
     
            public class ColumnControl : Control 
            { 
                private DataItem data; 
                private string columnName; 
                private string tableName; 
                private readonly List<DataItem> dataSet; 
                public ColumnControl(string columnName, List<DataItem> dataSet) 
                { 
                    this.columnName = columnName; 
                    this.dataSet = dataSet; 
                    DataBinding += ColumnControl_DataBinding; 
                } 
     
                void ColumnControl_DataBinding(object sender, EventArgs e) 
                { 
                    GridDataItem gridData = (GridDataItem)Parent.Parent; 
                    tableName = gridData.OwnerTableView.Name; 
                    DataRowView dataRow = (DataRowView)(gridData).DataItem; 
                    if (tableName == "Table1") 
                    { 
                        string item = dataRow[columnName].ToString(); 
                        HyperLink l = (HyperLink)FindControl(string.Format("{0}Label", columnName)); 
                        l.Text = item
                        l.NavigateUrl = "~"
                    } 
                    if (tableName == "Table2") 
                    { 
                        int rowNumber = (int)dataRow["RowNumber"]; 
                        data = dataSet[rowNumber]; 
                    } 
                } 
     
                protected override void CreateChildControls() 
                { 
                    //if (tableName == "Table1") 
                    { 
                        HyperLink l = new HyperLink(); 
                        l.ID = string.Format("{0}Label", columnName); 
                        Controls.Add(l); 
                    } 
                    if (tableName == "Table2") 
                    { 
                        foreach (Label c in data.Labels) 
                            Controls.Add(c); 
                    } 
                } 
            } 
     
        } 
     
  2. Iana Tsolova
    Admin
    Iana Tsolova avatar
    3388 posts

    Posted 20 Jun 2008 Link to this post

    Hello Steve Bough,

    Please try changing the hierarchy load mode of the MasterTableView to ServerBind or Client and enable the grid ViewState and check if it this makes any difference:

    RadGrid1.MasterTableView.HierarchyLoadMode = GridChildLoadMode.ServerBind; 

    Find more information about hierarchy load modes here.

    In addition, you can review this code library on how to retain expand state in hierarchy.

    Let us know if this directions are helpful.

    Regards,
    Iana
    the Telerik team

    Instantly find answers to your questions at the new Telerik Support Center
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Steve Bough
    Steve Bough avatar
    16 posts
    Member since:
    Jul 2007

    Posted 23 Jun 2008 Link to this post

    Thanks, the hierarchy state saving approach has sorted out my problems and solved a couple of others I had besides.
    As always, thanks for the swift and helpful response.
Back to Top