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.
Related
I have an ASP.NET page where I call this.DataBind() to bind the controls. I also have various user controls embedded. One has a drop down list, the bind statement gets called for it 2x but the sender the first time is not the drop down list.
Am I using the databind incorrectly? I use databind to get the properties of my page bound to a datasource so that I can use those properties in the declarative code.
In my DropDownList, I added if (sender == dropDownList) which solved the problem
Make sure that none of your user controls are themselves calling .DataBind()
.
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?
On Page_Init I create a table of dynamically created controls based on a couple of database tables. One of the controls is an ImageButton for moving an list item up the list. What this event handler does is to update the SortOrder column in the database for the affected items.
Now the problem is that since the controls are created in the Page_Init event and the SortOrder is updated later on when the ImageButton command event is fired. What's the best procedure for updating the table with the correct SortOrder. If I recreate the table after the event has fired the ImageButton command event does not work any more.
Should I implement a method for updating the data in the table without recreating it?
Should I reload the page in code after the event has fired?
What's your preferred way for solving this problem?
Page events such as Init and Load will always fire before the event handler that raised the postback. This is the basis of the Page lifecycle (For a visual representation by Peter Bromberg, see here). Most developers new to ASP.NET have a major problem understanding and appropriately handling this "quandary".
The ideal way to do this is:
a. Your Page_Init should call a procedure (let's call it BindData() for illustration) that handles the creation of the table based on database data. This method would be similar to a binding method that binds to the database data and renders UI elements on the basis of that binding. IOW, you should remove the table creation code from the Page_Init method and put it in a separate method so that it can be called when needed.
Important note: This BindData() method also handles the attaching of the eventhandler for the dynamically created ImageButton control to the control. We'll call this ImageButton_Click. This is crucial for the control to the event to fire on subsequent postback.
b. When your ImageButton_Click method executes, it calls the BindData() method to recreate the table and it's bindings but with new sort order rules.
So, the order of execution on first load is:
Page_Init
BindData()
The order of execution on subsequent loads (on postback) is:
Page_Init
BindData() - Eventhandler for ImageButton attached.
ImageButton_Click
BindData()
You'll need something like this...
OnInit (IsPostBack = false)
Dynamically create ImageButton
Wireup ImageButton Event Handler
Load Table - Check for a sort-order in Session/Variable. If none; use the default
Click the button
OnInit (IsPostBack = true / 1st Postback)
Dynamically re-create ImageButton
Wireup ImageButton Event Handler
Load Table - with default sort order
ImageButton_OnClick (Still the same 1st postback)
Reload Table - with specific sort order
Save this sort-order variable in Viewstate/Session variable
Cause some other Postback
OnInit (IsPostBack = true / 2nd & Subsequent Postbacks)
Dynamically create ImageButton
Wireup ImageButton Event Handler
Load Table - Check for a sort-order in Session/Variable. If FOUND, use that.
Firstly, you seem to be binding your data manually to UI controls. In Asp.Net there and many ways to avoid this using built-in data binding techniques. Many controls like the GridView allow automatic creation of Html tables from a given data source. There are many other options including Repeaters.
However you do choose to bind your data, the technique is to rebind at some point every time through the page lifecycle.
You need to...
Bind you data on first page load with the default sort order
Rebind the data in the image button’s event handler after the sort order has been changed.
The code would look something like this...
private void Page_Load (...)
{
if (!IsPostBack)
//On First Load
BindData(defaultSoortOrder);
else
BindData(currentSortOrder);
}
private void ImageButton_Click (...)
{
currentSortOrder = newSortOrder;
BindData(currentSortOrder);
}
If the Image button is clicked, you will end up calling BindData twice. But this is necessary since a page postback could be initiated from any control, you need to always ensure you bind the data when the page loads.
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.
I am adding some user controls dynamically to a PlaceHolder server control. My user control consists of some labels and some textbox controls.
When I submit the form and try to view the contents of the textboxes (within each user control) on the server, they are empty.
When the postback completes, the textboxes have the data that I entered prior to postback. This tells me that the text in the boxes are being retained through ViewState. I just don't know why I can't find them when I'm debugging.
Can someone please tell me why I would not be seeing the data the user entered on the server?
Thanks for any help.
This is based on .NET v1 event sequence, but it should give you the idea:
Initialize (Init event)
Begin Tracking View State (checks if postback)
Load View State (if postback)
Load Postback Data (if postback)
Load (Load event)
Raise Changed Events (if postback)
Raise Postback Events (if postback)
PreRender (PreRender event)
Save View State
Render
Unload (Unload event)
Dispose
As you can see, the loading of ViewState data back to the controls happen before the Load event. So in order for your dynamically-added controls to "retain" those values, they have to be present for the ASP.NET page to reload the values in the first place. You would have to re-create those controls at the Init stage, before Load View State occurs.
I figured out yesterday that you can actually make your app work like normal by loading the control tree right after the loadviewstateevent is fired. if you override the loadviewstate event, call mybase.loadviewstate and then put your own code to regenerate the controls right after it, the values for those controls will be available on page load. In one of my apps I use a viewstate field to hold the ID or the array info that can be used to recreate those controls.
Protected Overrides Sub LoadViewState(ByVal savedState As Object)
MyBase.LoadViewState(savedState)
If IsPostBack Then
CreateMyControls()
End If
End Sub
I believe you'll need to add the UserControl to the PlaceHolder during the Init phase of the page life cycle, in order to get the ViewState to be filled in by the Load phase to read those values. Is this the order in which you're loading those?
Ensure you are defining your dynamic controls at the class level and adding them to the ASP container:
Private dynControl As ASP.MyNamespace_MyControl_ascx
And when you instantiate the control, ensure you call LoadControl so the object is added properly:
dynControl = CType(LoadControl("~/MyNamespace/MyControl/MyControl.ascx"), ASP.MyNamespace_MyControl_ascx)
You have to create your controls in the Page_PreInit event handler. The ASP.NET server control model is tricky; you have to fully understand the page lifecycle to do it right.
As others have said, any form of control manipulation must be done before viewstate is created.
Here is a good link on the page lifecycle to help you out:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
We have experienced the same thing and have handled it by using ghost controls on page_load that have the exact same .ID and then the post back picks up the events and the data. As others said it's the dynamic adding of the control after the init stages that the state is built already and controls added after aren't stored.
Hope this helps a bit.
I also want to add that I've seen user controls work the way that you'd expect them to just by setting the Control.ID property at run time. If you do not set the ID, items may get built in a different order and work oddly.