views:

50

answers:

1

I have a Masterpage that has Treeview. You can select some nodes there. Based on the selection you get some items in the Default.aspx's Placeholder, you get a image and a linkbutton placed in a Panel. Like this :

alt text

This code is in the Default.aspx that has the Masterpage.

        TreeView nav_tree = ((TreeView)Master.FindControl("treeview_Navigation"));
        string selectedNode = nav_tree.SelectedNode.Value;

        var query = from n in dc.Nemanet_Navigations
                    where n.UserId == userGuid && n.Nav_pID.ToString() == selectedNode && n.Nav_IsFile == false
                    orderby n.Nav_Name
                    select n;
        foreach (var item in query)
        {

            Panel div = new Panel();
            div.ID = item.Nav_ID.ToString();
            div.CssClass = "BulletDiv";
            content_default.Controls.Add(div);

            Image picture = new Image();
            picture.ImageUrl = "~/Icons/New_Folder.png";
            div.Controls.Add(picture);

            div.Controls.Add(new LiteralControl("<br/>"));

            LinkButton description = new LinkButton();
            description.Text = item.Nav_Name;
            description.PostBackUrl = "default.aspx";
            div.Controls.Add(description);

        }

There seems to be problem when i create the controllers at runtime, when the site does a postback, lets say if i click "Enska" in the treeview i get the results in the image above. Lets say that i then click "The Punk Panther" i get a error.

An error has occurred because a control with id 'ctl00$CPH_Main$ctl05' could not be located or a different control is assigned to the same ID after postback. If the ID is not assigned, explicitly set the ID property of controls that raise postback events to avoid this error.

Also, how would i go by making a event handler for the linkbutton at runtime, can i make one event handler that every linkbutton uses or what ? I want the folder and the linkbutton to be clickable and link to the same place, is it simpler to make the whole Panel clickable, if so, how would i get a "OnClick" event on it ?

+1  A: 

Your problem is related to the sometimes difficult to comprehened ASP.NET Page Lifecycle.

The control hierarchy you create at runtime is not recreated at the correct point in the page life cycle during a postback request, if at all.

The "classic" approach that other web controls (e.g. DataGrid) take to tackle this problem is to serialise the data loaded into them into viewstate so that on postback, the control hierarchy can be reconstructed from postback values alone (without having to query the database again). However, implementing such an approach may not be appropriate in your circumstance.

Instead, you could build an array (or other serialisable enumeration) of item key values (item.Nav_ID) that were used to build the previous control hierarchy, and add this to viewstate, e.g.:

List<Int32> navIdValues = new List<Int32>();
foreach (var item in query)
{
    navIdValues.Add(item.Nav_ID);
}
Page.ViewState("NavIdValues") = navIdValues

Then, during the Page.Init event of an incoming postback, retrieve the values you used to build the control hierarchy in the previous request:

List<Int32> navIdValues = Page.ViewState("NavIdValues") as List<Int32>;

Re-execute your query, building a dictionary of item's accessible by their Nav_ID:

IDictionary<Int32, ??itemtype??> items = query.ToDictionary(n => n.Nav_Id);

And then re-build the control hierarchy as it existed in the previous request:

foreach (Int32 navId in navIdValues)
{
     var item = items(navId); 

     Panel div = new Panel();
     div.ID = item.Nav_ID.ToString();
     div.CssClass = "BulletDiv";

     ... etc ...
}

Then your postback event's should fire as expected, because the control hierarchy has been recreated before postback event handling. This may not be the most optimal solution, but is a workable one.

Rabid