ASP.net: dynamically load web user control - asp.net

I have a asp.net web page with place holder control and Menu control when user select an item from the menu. It will dynamically load the control based on menu item's value.
I got the control loaded but if i click on the a link button or anything on the web user control (.ascx) The web user control (.ascx) will disappear. I do not know what is causing this. Can someone take a look at my code and see what i'm missing?
Protected Sub Menu1_Click(ByVal sender As Object, ByVal e As EventArgs)
Select Case Me.Menu1.SelectedValue
Case "CustMasterMain"
Dim ccCustMasterMaint As UserControl = CType(Page.LoadControl("~/Controls/Franchise/CustMasterMaintControl.ascx"), UserControl)
Me.phHolder1.Controls.Add(ccCustMasterMaint)
Case "AcctRecInq"
Dim ccAcctRecInq As UserControl = CType(Page.LoadControl("~/Controls/Franchise/custAccountsReceivableInquiry.ascx"), UserControl)
Me.phHolder1.Controls.Add(ccAcctRecInq)
End Select
End Sub

Remember that each time you do a postback you are working with a brand new instance of your page class. If you added the control to the controls collection of a previous instance of your page class, you need to add it again for every postback that follows.
Additionally, if you want ViewState to be restored for the control then it needs to be added to the page before the Load event. That means adding the control during Init or PreInit.

Joel is correct that you need to add the control on every postback so you need a way to track what controls are stored on the page.
The Dynamic Controls Placeholder is an excellent control for helping manage dynamic controls on your page across postbacks. I'd recommend you check it out as I've used it on a number of projects and it's made life a lot easier for me.

Related

How to Populate ListBox without PostBack in ASP .NET?

My Web Form consists of two Listboxes lstbx01 and lstbx02. lstbx01 is databound to sqlDataSource01 and it Populates on Page Load Event. lstbx02 is set to populate when the selected value of lstbx01 is passed as a Parameter to sqlDataSource02. Everything works fine if lstbx01 has its AutoPostBack property set to True.
I do not want the page to be Refreshed. I want to set the lstbx02 to populate without page being PostBack.
I have tried the below mentioned Code:
Protected Sub lstbx02_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstbx02.SelectedIndexChanged
lstbx02.DataSource = sqlDataSource02
lstbx02.DataBind()
End Sub
This doesn't help.
I do not think that what you are asking would be possible in WebForms. The code you provided would require a postback to transmit the event back to the server so it can be handled.
Is there a specific reason you cannot do a postback? A possible workaround would be to use AngularJS, Knockout, or some other JS framework to populate inputs on the page. You would then need an event handler that either used AJAX to fetch the relevant data or displayed data that has been cached into the page as JSON.

How to switch among tabs with the Ajax Control Toolkit TabContainer?

I have 3 ascx controls loaded in one aspx file as a tabbed manner. I have one button in first ascx control. If the button is clicked then I have to move to next tab. How to move to next tab?
I assume that you or your organization wrote the 3 ascx controls?
You're going to have to alert the parent of the tabbed control (the page?) that a child of the tabbed control (the ascx control) has requested that the tab control progress to another tab.
The simplest, least coupled way I know how to do this is with a custom event. The steps would be as follows:
Implement an event in your ascx control that is raised when the button in your ascx control is clicked. There's an example of this in this Q+A.
Since you're using Visual Basic, the syntax for the fourth step will be different. I describe this in the next step, below.
Set up a handler for that event in the page. (This is Step 4 in the example I linked to.)
The simplest way to associate the handler with the user control is in the markup:
<uc:MyUserControl TabChangeRequested="MyUserControl_TabChangeRequested"
runat="server" id="userControl1" />
This example assumes that MyUserControl_TabChangeRequested is a public or protected method of your page.
If this doesn't work, you can do the association programmatically. How you do this depends on whether the user control is visible to the page itself, or is a child of the tab control. If the user control is a child of the page, you can use this code (in Page_Load):
AddHandler userControl1.TabChangeRequested, AddressOf MyUserControl_TabChangeRequested
It's a very different syntax to that of C#, which can make examples confusing.
If the user control is a child of the tab control rather than being declared at the page control, you need to first get a reference to the user control from within the control collection of the specific tab:
Dim uc as MyUserControl = TabControl1.Tabs(0).FindControl("userControl1")
AddHandler uc.TabChangeRequested, AddressOf MyUserControl_TabChangeRequested
Depending on the tab control and how it was written, you might need to look in the tab control's own children rather than the tab's. The first line of the previous example would look like this:
Dim uc as MyUserControl = TabControl1.FindControl("userControl1")
In your handler, do whatever you need to do to change to the next tab.

How do I RegisterPostbackControl in an AsyncPostback for Telerik RadGrid

I have a RadGrid in a page which has a master page with an UpdatePanel wrapped round the Content.
I have successfully run RegisterPostbackControl for the Export buttons on it on first load, thus:
Private Sub uxGrid_ItemCreated(ByVal sender As Object,
ByVal e As GridItemEventArgs)
If TypeOf e.Item Is GridCommandItem Then
Dim sc As ScriptManager = CType(Master.FindControl("Sc"), ScriptManager)
RegisterPostBackControl(e.Item.FindControl("ExportToCSVButton"))
End If
End Sub
This works, and if I press the export button it does a full postback and exports a file.
I have another control on that page (a date control), which changes the content of the grid, and that posts back asychronously.
The trouble is, once I've done one asynchronous postback, I cannot register the control again, and the export button no longer fires a full postback. I have tried putting the RegisterPostback in as many different places as I can think of - RenderComplete, Init, Load, PreRender, etc, but it seems to no avail. Once it's in an asynch postback, I cannot register it.
Some other code I tried:
For Each cmdItem As GridCommandItem In
uxResponse.MasterTableView.GetItems(GridItemType.CommandItem)
sc.RegisterPostBackControl(cmdItem.FindControl("ExportToCSVButton"))
I know I can switch off asynchronous postback altogether, but I'd much rather have the responsiveness, and this is the only thing which is broken.
Has anyone else had this problem and sorted it?
I sorted this by bypassing the problem: I amended the aspx page to have an export button on it all the time (not dynamically created), registered that for postback, and used CSS to put the new button in the same place as the old button.
Not particularly nice, but it works as a kludge.
If no-one knows a better way, I'll mark this as the answer in a while.

How can I handle a button event that triggers user control creation?

I have an ASP.NET web form on which I'm displaying a list of database items via user controls, generating the user controls dynamically - working fine.
Also on the page, I have an asp:dropdownlist filled with items that can be added to this database list. Along with this dropdown I have a button 'ADD'. My intent is that the user chooses and item, clicks add, and then the list of user controls on the form will include this new item.
I have all this working.
My issue is that the user control has a button 'DELETE', which removes the selected item from the list. That works, EXCEPT when I add a new item. Because my 'add' button event is always fired after Page_Load, even if I regenerate the list of user controls, the internal user control click events won't fire because the controls weren't created as part of Page_Load.
I need to know what I'm doing wrong, or best practices here, any advice. I tried to be precise in the description of the problem, but if I've not succeeded, let me know and I can add more details.
SIMPLE RESTATE: I need to know how to add a dynamically created user control to a page via a page button click event, and still have the user control internal click(etc) events firing.
Thanks for any help.
EDIT: Based on the feedback from the gentlemen here, and doing some further research related to their suggestions, I ended up implementing a solution based on what's presented on this page:
http://ryanfarley.com/blog/archive/2005/03/11/1886.aspx
Here's a snippet showing how I dealt with this. This snippet resides in my PreInit event handler. Not exactly an elegant weapon for a civilized age, but sometimes a blaster is all you've got to use.
'Look to see if button for adding a new client number has been
'clicked. If so, call the sub to add the item NOW, so that it
'is able to have it's internal click events fire.
For Each control_string As String In Request.Form
Dim ctl As Control = Page.FindControl(control_string)
If (ctl IsNot Nothing) AndAlso (ctl.ID = "cmdAddClientNumber") Then
Me.AddClientNumberToList()
Exit For
End If
Next
On the button handler, you initially add the UserControl to the Page. OnPreInit (which will next be fired when the user clicks Delete on the UserControl), you should re-add the UserControl - so that it exists, and can handle the Delete button event.
You will need to devise your own state tracking mechanism to determine that you need to add the UserControl during PreInit. I generally use ViewState, as evidenced by this seemingly similar post.
Similar question:
How to create and use custom control with UpdatePanel added to the page programmatically
Dynamic control should be re-added to the control tree OnPreInit, see documentation:
PreInit - Create or re-create dynamic controls.
ASP.NET Page Life Cycle Overview

ASP.NET Button click not caught (button in user control which is dynamically loaded in Repeater)

I have written a user control that captures some user input and has a Save button to save it to the DB. I use a repeater to render a number of these controls on the page - imagine a list of multiple choice questions with a Save button by each question.
I am loading the user control inside the repeater's ItemDataBound event like this (code simplified):
Protected Sub rptAssignments_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptAssignments.ItemDataBound
Dim CurrentAssignment As Assignment = DirectCast(e.Item.DataItem, Assignment)
Dim ctl As UA = CType(LoadControl("~\Controls\UA.ascx"), UA)
ctl.AssignmentID = CurrentAssignment.AssignmentID
ctl.Assignment = CurrentAssignment.AssignmentName
ctl.EnableViewState = True
e.Item.Controls.Add(ctl)
End Sub
FYI, I need to load the control at runtime rather than specify it in the ItemTemplate because a different control could be used for each row.
In the user control, there is a linkbutton like this:
<asp:LinkButton ID="lbnUpdate" runat="server" Text="Update" OnClick="lbnUpdate_Click" />
... and a button click handler like this:
Protected Sub lbnUpdate_Click(ByVal sender As Object, ByVal e As EventArgs) Handles lbnUpdate.Click
' my code to update the DB
End Sub
The problem is that when the Save button is clicked, the page posts back, but lbnUpdate_Click is not called. The Page_Load event of the page itself is called however.
I should mention that the repeater is part of a user control, and that user control is loaded inside another user control (this is a DotNetNuke site which makes heavy use of user controls). The Save button link looks like this:
javascript:__doPostBack('dnn$ctr498$AssignmentsList$rptAssignments$ctl04$ctl00$lbnUpdate','')
This problem exemplifies how webforms outsmarts itself.
You have to reconstitute the Repeater, either by re-binding or from viewstate, to have sub-controls raise events. The price you pay is either another trip to your data source or all that redundant data stored on the client in the viewstate. Shameful!
I had a similar problem once that might be the same thing.
In short, since you are dynamically creating the buttons, after the postback they don't exist. Thus, when ASP.NET Webforms looks for the event, it can't find anything.
When does your repeater get databound? Try rendering the buttons to the page again in the postback (even as a test) to see if that does the trick.
Are the UserControl's IDs same on every postback?

Resources