Load User Controls dynamically based on other control events - c#

I have a "cross section" of variables that I need to use to generate a set of user controls dynamically. In the center of the page I have a Telerik multitab/page. I have a custom tree menu and a custom menubar, based on the combination of menu input each of the tabs should load a user control relevant to that cross section of data.
For clarity, almost each tab, treeview, menubar combination needs a unique control.
My problem is that all the postback/loading happens well before the "OnMenuChanged" event triggers, so I'm one "set" of user controls behind. Even if I were to use session/viewstate they wouldn't get assigned until after I needed the value stored in them.
Currently what is happening is the default user controls are loaded in the "pageviewcreated" event, then in the onMenuItemChanged I go back and reload the user controls. It seems very inefficient and is complicating up the approach for selecting the right .ascx.
How do I manage this?

If I understand what you're trying to do could you not use a placeholder control and inject your needed usercontrol into that inside of the events you're managing? Try doing something like this inside of the "OnMenuSelected" event.
WebUserControl1 uc = (WebUserControl1) Page.LoadControl("WebUserControl1.ascx");
PlaceHolder1.Controls.Add(uc);

Related

Move UserControl to another parent in Page Stack

I have a page of controls that I want to be able to move specific controls by ID to a different parent control server side.
A simple example being another control loads 2 controls vertically ontop of each other. I want a module that can reference those two modules by ID and lay them out horizontally.
I assume this would have to done after the Page_Load() event so that all the controls are loaded.
I think I can accomplish this with a recursive control.FindControl() but I'm thinking there is a more elegant way.
If you plan to dynamically move controls around the page then it’s better to programmatically set them on page where it’s needed.
You should be adding controls in the OnInit method that is run before the page load.
Roughly, the OnInit method would look like
a) check the state of the page and decide where to add control
b) add control where needed

Saving focus state using GetFocusedElement() not working with user controls on a Panorama control

I am trying to use the 'best practice' technique of using the
FocusManager.GetFocusedElement()
in the OnNavigatedFrom event and
this.FindName
to locate the focused control in the OnNavigatedTo event.
I have a Panorama page and within each PanoramaItem I have a user control which in turn have many controls such as TextBox's etc..
The GetFocusedElement does retrieve the focused controls name in the user controls, but the FindName method then fails to find it on return! The name returned does not include any reference to the user control itself, so I am assuming the FindName does not traverse user controls!
Am I doing something wrong or does anyone know a way of easily improving this, or at least a simple technique for at least showing or navigating too the last PanoramaItem that was displayed before the app is deactivated?
To set the selected panorama item when the page is navigated to use the DefaultItem property.
To determine what this should be, save the SelectedItem when navigating away from the page.
You should be doing this at the page level and accessing properties of the panorama. There should be no need to do anything in the controls hosted in a panoramaItem whether they are user controls or not.
If you wish to avoid the side effects of altering the defaultItem, you may want to have a look at http://blogs.ugidotnet.org/corrado/archive/2010/09/27/smartpanorama-a-panorama-control-extension.aspx

How do I add events to nested server controls? (ASP.Net)

I am building a custom master page type control i.e. sort of like a datagrid but should be easier to add custom functionality into it. It's going great but part of the desired functionality is to have a paging control that switches on and off and part of that control would be a textbox that displays the current page number and on TextChanged redirects to the new page of the dataset.
The problem I'm having is that technically the textbox which has its event fired is embedded in a control that is embedded in the control you actually put on the page sort of like
Page
|
Display Control
|
Paging Control
|
Textbox
Buried all the way down there the event is not firing. Worse the postback javascript isn't even being written onto the page (Nothing on the page posts back so far this is the only bit that really needs to).
I've been trawling around Google for quite a while now and picked up that I need to implement INamingContainer (done) and I need to add the control into the page's control tree (is Pre_Init too late for that? When's a good time to Add the Control to the page?) then the event should fire, apparently. But I've been unable to find an example of best practice on this there are quite a few near misses where people are having button angst but this isn't a button.
So can anyone point me in the direction of getting a control embedded in a control embedded in a control added to a page to behave properly?
You need INamingContainer only if you plan to add more than one instance of your custom control to the same page. What it does is enabling unique id generation so you don't end up with controls with the same ID. I recommend you inherit from CompositeControl when creating your custom control.
Pre_Init is not too late. Actually it is pretty early considering the lifecycle. You can instantiate custom controls and add them to the live controls collection in a lot of places. I would recommend you do it in Page_Init (before viewstate is loaded) or Page_Load(after view state is loaded). Even if you add it later in the page lifecycle the control will catch up in events.
To subscribe to events of child controls you can use the FindControl method:
MyControl myControl = Page.FindControl("MyControl1");
TextBox textBox = myControl.FindControl("TextBox1") as TextBox;
The answer was a combination of the above answer and the comment on the original question. The vital thing to get the event to happen is to make sure that your controls (parent and child) inherit from CompositeControl and INamingContainer e.g.
public partial myControl:CompositeControl,INamingContainer
etc...
Then you override your composite control's CreateChildControls() method and create your controls and do the wire up there. This will ensure correct bubbling. and mean that the event handling takes place within your comoposite control...

Adding a list of UserControls with buttons to a PlaceHolder - no event?

I want to make use of "complex" usercontrols with more than one control element within. It's the same control I will reuse in the list, and I have a PlaceHolder control for it already.
I can add the control with LoadControl(path to .ascx) - no problem.
I can through my custom properties get/set access the embedded Labels, too, so I can initialize each control perfectly.
But when adding LinkButtons, I get into trouble/problems.
When I click the button, I do get a "submit" of the page rendering the controls; but the control's own button event does not seem to fire (or at least PageLoad on the parent page seems to fire first?) - I can't figure out where my event goes or where to look for a name/ID or parameter for this button.
How come or what am I doing wrong here?
I've made a "fake button" now by using a label more with a "hardcoded A HREF" with an ID in the URL, but I would like to learn what event I need to catch and where or how to init the button, because I want to be able to use "default ASP.NET" controls for these usercontrols (hopefully without too much patchwork-coding)...
The only reason that events get "lost" is because your controls are not being recreated in such a manner that ASP.Net can associate the event with the control after the postback. It does so through the use of the ID property.
In other words, you're doing one of three things wrong:
1) You're assigning the ID's of your linkbuttons differently during the creating phase in Init after the postback
2) You're creating your linkbuttons dynamically using code, but you're doing it after the Init phase of the page lifecycle, so that your controls do not participate in ViewState.
3) You're re-binding the datasource of the parent control containing the linkbuttons on every postback. Use if (!IsPostBack) to prevent rebinding it every time.
Without seeing your code I can't give anything more specific than that unfortunately.

problem with viewstate of dynamic controls inside a repeater

I ran into a problem recently when using a repeater that I was adding dynamic controls into and although I've got a workaround that does functionally exactly what I want it to do, I'd like to know if there is a better way to do it for my understanding. I've been working with ASP.NET for about 6 months now, and everytime I think I've got the page lifecycle/viewstate completely sussed something crops up that I can't answer.
I was creating a form where users could register their interest for an event, and register for multiple people.
The aspx went something like:
<asp:Repeater ...>
<bunch of formatting and always there controls like firstname/lastname/address>
<asp:PlaceHolder ...>
<dynamic controls for workshop selection go here>
</asp:PlaceHolder>
</asp:Repeater>
An event can have workshops that the user can register for, and the availability of the workshops is dependant on the date that they choose to go to the event on. The availability of the workshops is dependent on the date, so they can't choose the workshops until they've selected a date.
Anyway the dynamic controls that I'm adding are basically a bunch of literals and a bunch of radio button groups.
I started off by adding the controls in the ItemDataBound event handler, but when saving my repeater items back to my delegate list the ViewState of the radio buttons was never updated. All the fields that were referenced in the ItemTemplate were handled fine, but not the radio buttons I was adding dynamically.
I tried to use the ItemCreated event instead, adding my buttons there, but that didn't seem to make any difference. In the end I settled on a workaround which was based off of this. Basically I'm just outputing the HTML input fields in a literal and reading them back from the request.
It all works perfectly now, and I'm happy with the functionality, it just seems really dirty to have to output the radio buttons as HTML inputs directly rather than use a server side control. Does anyone have a clue about why the ViewState wasn't being restored properly?
Just to be clear, the controls were recreated in the same order everytime, with the ID properly set. I'm using dynamic controls all over the place and they're working fine, I just can't get them to work in this case when I'm adding them inside a repeater.
//more clarification
I can't create these controls in Page.Init as the user selects the date which causes a postback and I have to wait for the viewstate of that control to load before I create the dynamic controls.
You're creating (or re-creating) the controls when the repeater is bound to its data source. If this happens after the ViewState has been loaded by the page, the ViewState won't be available to the dynamically-created controls.
Check you're binding your repeater early enough - Page.Init is OK; Page.Load is too late.
It is worth noting that Radiobuttons controls do not work 'out of the box' in repeater controls. Repeater controls inherit the INamingContainer interface which ensures all rendered html controls have unique name attributes. As radio buttons use the name attribute to group themselves this means you will not be able to create groups of radio buttons i.e. setting the GroupName property will not have the desired effect as the Repeater will override this and create unique names for each RadioButton.

Categories