Question

Suppose I have a treeview, where each treenode contains an id for a different set of user controls. When the user clicks a node, these controls should be loaded to the page. As I understand the ASP page life cycle, dynamic controls should be added in the initialization stage, and postback events will fire later on.

So if the treeview click event happens after I need to add my controls, how do I dynamically add controls based on user postback events?


Edit: I tried the suggestion from ArronLS:

What I did was add the node value to the session array, and use that when I do the init to choose which form elements to load to the controls of a placeholder control. On the treeview click event, I update the node in the session array, clear the old form elements in the placeholder, and add the new form elements to the controls. When the page is loaded again, it should now find the node at init time, so viewstate problems would be circumvented.

Now I haven't fully tested this yet, but there was another similar post that talks about the problems that might result with the viewstate. They suggest a solution that polls the Request[] part of the context (in their case the dropbox) within the Init control, manually handling some of the postback functionality.

My new question is how to I access the selected node in the treeview using the Request array?

Was it helpful?

Solution

The consequence of not loading the controls in init is that if there are changes to properties in the view state, these will not get persisted to the controls. For example, if on the first request of the page, you dynamically create controls in init, then on the post back you create them again in init, then after init, any property values in viewstate get applied to the control.

So if you created the control initially in a treeview click event, I would guess that should be fine, because there is not yet any viewstate accumulated to apply to the control since it was just created. However, I am not sure if this will cause the control to not save viewstate. You'd have to experiment with that.

On subsequent postbacks after the first, now you will need to create the control in init for accumulated viestate to be applied to it, so you'll need some mechanism to "remember" that you created the control once before, initially in response to the click event, and then on subsequent postbacks create the control again in init. You have to recreate the control on each request, if you didn't know that.

So the question becomes how important is the viewstate for the control.

Edit: I will also add that I am not entirely sure if there would be other consequence other than how this affects viewstate.

OTHER TIPS

This may not be an answer to your direct question, but since I've never found an answer myself, here's the workaround I've used.

The approach I've always used when working with a TreeView is to declare the controls in the aspx page once, and then on the click event, bind the controls the the data based on the id. If necessary, you can initially set the visibility to visible="false" and change it when bound. This approach works nicely because it avoids just the conundrum you're describing.

If you're not opposed to giving up on treeviews, a nested repeater approach works well, too.

Just throwing out another thought, hoping to get some more feedback...

I could use the postback event to define the selected value in the session array, and then force the page to redirect to itself. Then, the init that the user sees will effectively be done after the event handler has fired.

Seems like a bad idea, so I'm hoping for something else.

If I've understood you correctly you want different content shown for each tree node. I'm assuming theres the treeview on the left and some content area in the middle.

From a UI perspective I normally solve this by using a MultiView where each individual View is a seperate usercontrol with the required content. The treenode click event simply changes the MultiView ActiveIndex contained in the Node value property (ID is stored in the DataItem) and you simply switch out the content area.

Generally, even if the tree nodes are dynamically generated, from data for example, there will only ever be a finite amount of "Node View" usercontrols that you need to define.

Note. Be careful when using the MultiView control as all Views contained are loaded during the page life-cycle so dont put any "heavy-lifting" into Page_Load etc.

It may help to remember that the ID of the selected node is passed as a form value, which is always accessible from the Request.Form collection, even during the Init event. The key would be something like ctl00_Content1_TreeView1_SelectedNode. However, that ID alone would probably not get you the value you need, so you would want to look at Request.Form["__EVENTARGUMENT"] and also use Request.Form["__EVENTTARGET"] to verify that it was indeed the TreeView that caused the PostBack.

More than likely the information you need can be pulled out of the Form collection. It's just a matter of setting a breakpoint and examining the values. This kind of code always feels awfully hacky but in this case you just can't wait for the TreeView control's event to be handled when you need to use the values submitted in the form to do something during Page_Init. Just don't be afraid to look at the form values instead of waiting for .NET to package it all up nicely with strongly-typed properties. By then it will be too late.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top