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

Hierarchical Business Object bind problem

6 Answers 88 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Dexx .
Top achievements
Rank 1
Dexx . asked on 17 Oct 2012, 02:19 PM
Dear Supporter,

I've just started using Telerik, I could achieve a few things very nicely, but now I've run into a strange problem.
I'm trying to bind a grid to a hierarchical structure of business objects. I've set up the NeedDataSource event handler and even the DetailTableDataBind, and with the HierarchyDefaultExpanded = true parameter the hierarchy displays in the grid just as I need, the problem comes when the detail tables get collapsed and expanded again.

The code behind for a simple RadGrid (with 'RadGrid1' name):

public partial class Default : System.Web.UI.Page
{
    public class Customer
    {
        public int id { get; set; }
        public string name { get; set; }
        public string city { get; set; }
        public List<Contact> Contacts { get; set; }
    }
 
    public class Contact
    {
        public int id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
    }
 
    public static List<Customer> Customers = new List<Customer> {
        new Customer() { id = 1, name = "Bridget", city = "New York", Contacts = new List<Contact>() {
                new Contact() { id = 1, name = "John", email = "johnny@hotmail.com" },
                new Contact() { id = 2, name = "Mark", email = "mark@hotmail.com" }
            }
        },
        new Customer() { id = 2, name = "Carol", city = "London", Contacts = new List<Contact>() {
                new Contact() { id = 1, name = "Henry", email = "henry@hotmail.com" },
                new Contact() { id = 2, name = "Hugo", email = "hugo@hotmail.com" },
            }
        }
    };
 
    void RadGrid1_DetailTableDataBind(object sender, GridDetailTableDataBindEventArgs e)
    {
        GridDataItem dataItem = (GridDataItem)e.DetailTableView.ParentItem;
        e.DetailTableView.DataSource = ((Customer)dataItem.DataItem).Contacts;
    }
 
    void RadGrid1_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
    {
        if (!e.IsFromDetailTable)
            RadGrid1.DataSource = Customers;
    }
 
    protected void Page_Init(object sender, EventArgs e)
    {
        RadGrid1.NeedDataSource += RadGrid1_NeedDataSource;
        RadGrid1.DetailTableDataBind += RadGrid1_DetailTableDataBind;
    }
 
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            RadGrid1.MasterTableView.HierarchyDefaultExpanded = true;
            RadGrid1.MasterTableView.AutoGenerateColumns = true;
 
            RadGrid1.MasterTableView.DataKeyNames = new string[] { "id" };
 
            GridTableView contactsTable = new GridTableView(RadGrid1);
            contactsTable.AutoGenerateColumns = true;
 
            RadGrid1.MasterTableView.DetailTables.Add(contactsTable);
        }
    }
}


When I collapse a detail table (by clicking on the expand/collapse button at the left side of the master row) and when I try to expand that again, the DetailsTableDataBind event handler throws an exception, because it doesn't receive the real business object (of the master row) which would contain the needed Contacts child list (the dataItem.DataItem in  RadGrid1_DetailTableDataBind event handler is null after the collapse+expand action, but at first render it contains the needed Customer object as needed).

I have no more idea about the issue and I searched over the forum and googled a lot, but I always find solutions which binds to dataset or sqldatasources, but in our case custom classes is the only option.
I don't think I'm doing everything badly because the grid in full expanded mode displays correctly, only after collapse+expand the child table disappears (actually I think the master row's datasource is lost somewhere).

The pasted sample is a simplified version of our current situation, but it reflects my problem.
Btw. I was using RadControls for ASP.NET AJAX Q2 2012 SP2, Bin40 assemblies, 2012.2.912.40 versions.

Any help would be appreciated.


Regards,
Dexx

6 Answers, 1 is accepted

Sort by
0
Jayesh Goyani
Top achievements
Rank 2
answered on 17 Oct 2012, 05:20 PM
Hello,

Please try with below code snippet.
Method1:
protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                RadGrid1.MasterTableView.HierarchyDefaultExpanded = true;
                RadGrid1.MasterTableView.AutoGenerateColumns = true;
                RadGrid1.MasterTableView.HierarchyLoadMode = GridChildLoadMode.Client;
                RadGrid1.MasterTableView.DataKeyNames = new string[] { "id" };
 
                GridTableView contactsTable = new GridTableView(RadGrid1);
                contactsTable.AutoGenerateColumns = true;
 
                RadGrid1.MasterTableView.DetailTables.Add(contactsTable);
            }
        }

OR

void RadGrid1_DetailTableDataBind(object sender, GridDetailTableDataBindEventArgs e)
       {
           GridDataItem dataItem = (GridDataItem)e.DetailTableView.ParentItem;
           string strId = dataItem.GetDataKeyValue("id").ToString();
           e.DetailTableView.DataSource = Customers.Where(c => c.id.ToString() == strId).FirstOrDefault().Contacts;
       }


Thanks,
Jayesh Goyani
0
Dexx .
Top achievements
Rank 1
answered on 17 Oct 2012, 07:32 PM
Hi,

thanks for spending time to answer my problem.
The Method1 is not effective for my current scenario because the whole hierarchy would be sent to the client and for a big list (and for the real case it will be) it would take too much time and network traffic.

The Method2 seems to work, thx for that, but I have a little conception problem with it. The real hierarchy structure would come from a webservice, and that cannot and shouldn't be always called when the Customers list needed to be searched again when a child table is being expanded (the static list is only for the test purposes). As I understand, RadGrid stores the initially given datasource in the ViewState, so it's already stored for the grid, I just don't know where does it go when a child table being expanded, because when the mentioned dataItem.DataItem is null (when expanding), then the RadGrid1.DataSource is null too!! However the master rows are displayed correctly, so I don't really understand.
Do you have idea for that why the datasources disappear? I guess the master row (Customer object) should always be available  for the DetailTableDataBind event as I have to know about the parent (master) object whose detail table should be expanded. Not right?


Tanks in advance,
Dexx
0
Dexx .
Top achievements
Rank 1
answered on 19 Oct 2012, 06:37 AM
Sadly I didn't receive any further information about this issue.
I've googled for a few hours, and the best thing I could achieve is to set the following:

RadGrid1.MasterTableView.HierarchyLoadMode = GridChildLoadMode.Server;

This way the whole grid (with its detail tables) get bound to the whole strcuture at first init, and as I mentioned at the first init we have the dataItem.DataItem (not null) so the original process works. However this way all the detail tables get bound even if not all of them will be expanded, so this solution has an unneccessary overhead, which I'm not happy for.

The other solution I figured out is: store the 'Contacts' list too with the DataKeyNames, this way this information is available next to the parent item's 'id' property.

RadGrid1.MasterTableView.DataKeyNames = new string[] { "id", "Contacts" };

This way in the DetailTableDataBind I'm able to get the needed list of contacts (which now belongs to the parent item):

e.DetailTableView.DataSource = dataItem.GetDataKeyValue("Contacts");

And it also works with ServerOnDemand load mode, so this is the best solution I could figure out. However I still don't know how this double storing of this Contacts list affects the ViewState (because as I understand, it's stored for each item, and this way it's already stored for the parent row item and for the 'main' datasource (as it's serialized too I guess), so it could mean a big memory problem for big tables if it's really serialized twice).

It's a bit frustating not to get a solution for my scenario from professionals, and what I found is not the most reasonable solution I guess, because the ViewStats is being messed up with double storing the child element's list, but that's the best I could figure out.
I'm closing this thread as I see no more help coming. Btw I've run into another strange behaviour, I'll open a new thread for that, but if I don't get solution for that too, I think our company needs to look for another control library because I won't be able to pick telerik, even if I like it at first sight.

Dexx
0
Andrey
Telerik team
answered on 23 Oct 2012, 06:13 AM
Hello,

The approach you have found out is good and should help you achieve your goal, however, the big sets of data are always a problem with the ViewState usage. 

Additionally, please note that the forum posts does not have guaranteed response time as the support tickets do. With the forum threads you are counting on the community only. If you wan to have guaranteed response time you should submit a support ticket. If you have a valid license, please ask the license holder to add you as a licensed developer, so you could use the priority support.

Kind regards,
Andrey
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
Dexx .
Top achievements
Rank 1
answered on 23 Oct 2012, 09:41 PM
Hi,

we have no valid license, yet, because we're exactly in the phase of trying Telerik products to decide if we are willing to purchase this package. I understand this doesn't mean priority support, I just hoped I can get help for my first test situation as my issue looks like to me a very basic scenario. I've found a lot of samples for binding, but almost all of them was using SqlDataSource or its 'friends'. I barely found examples about binding to simple custom objects (like my sample), especially for hierarchical case.

Regards,
Dexx
0
Andrey
Telerik team
answered on 26 Oct 2012, 01:10 PM
Hello,

If you are evaluating our products, you could download a Trial package that will allow you to submit support tickets for a limited time. During this time you could open support tickets with a guaranteed response time of 72 hours and you could supply your project. Thus we will be able to investigate the issue and let you know what could possibly cause this behavior.

Here you could check here the available support options.

You could download a Trial by the Manage Products menu of your account.

Kind regards,
Andrey
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
Dexx .
Top achievements
Rank 1
Answers by
Jayesh Goyani
Top achievements
Rank 2
Dexx .
Top achievements
Rank 1
Andrey
Telerik team
Share this question
or