User Control in Master Page loads first - asp.net

I have a User Control in a Master Page that calculates quantity of products in the shopping basket and writes to page something like shopping cart(2), showing that you have 2 products.
When you add a product to basket, User Control loads first and then Add method of the page executes because of the page life cycle.
So In order to see the new added product takes effect - shopping cart(3) - i need to refresh the page..
What is the best solution in order to see this after add to cart button is pressed with no refreshing the site.
Do I need to use master page's pre_render event?

Having a look at the ASP.Net page life cycle, you'll find that the LoadComplete (for pages only) and PreRender events are called after the postback handlers.
It should be sufficient to move your shopping cart calculation into the User Control's PreRender event.

Just take care of the actual order of event execution, and call your logic accordingly:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Normally the Master Page UC should subscribe to an event which is fired by the page whenever an item is added.

Best way of doing is to use the custom Event in user control.
How ever if you don't want to use that, you can use a work around. Simply create a property of user control to show count and updates its value in Add method of that page.

Related

Click event of Link button inside a gridview of user control not working when the control is added dynamically in a web page asp.net?

On clciking a button in the page , I am adding an user control in to a place holder of the page.
The user control has a gridview which has a link button as template field and has a click event associated with it.
When I click the link button inside the gridview , the link button click event is not fired and also the user control disappears in the page.
Please suggest a solution
--You need to recreate all your dynamic controls at the early enough in the page lifecycle (page_load/page_init), so the asp.net will detect events and attach them.
try this knowledge post
http://support.microsoft.com/kb/317794
Why don't events of dynamically added user control fire on postback?
You need to recreate your dynamic controls on every postback - remember a new class instance of your page is created every postback, so any dynamic controls you created the previous time will need to be recreated.
see this article
and this one

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

jQuery/AJAX redirect?

Ok, this is a bit different scenario. I guess I would have to think about doing it this way sort of with MVC anyway if we were actually using MVC...but we're not at the moment.
So I've got and .aspx page. In that .aspx page is a user control (.ascx). And in that user control is a custom control (.cs).
The custom control has a repeater in it. So I'm showing a list of items on that .aspx through the .ascx's custom control. For each item in the repeater is a button. It's just a hyperlink, just a regular on my page
When you click that button, it redirects to whatever page you're on. Since the custom control never knows what your parent .aspx page is, I'm doing a redirect to the self .aspx by doing a Response.Redirect(Request.Path). So that way it always redirects to whatever .aspx is using that user control and custom control.
So after it redirects to self, I check the querystring in the page_load of whatever .aspx is using it. If the value is true, then I handle it however the .aspx wants to. In this case when it's true, I call a method in the code behind of my .aspx that handles the action for the button. For example lets say that button was "Add to Shopping Cart", the .aspx handles that action and calls a AddToCart method in the .aspx.cs.
I'm not using an ASP.NET control for the actual hyperlink and button because I just don't need it and in my particular case I'm using a user control and a custom server control. For this instance, I had some issue where I didn't wnat to use an ASP.NET control...I forget why but the point is, no this is what it is.
So with that, I'm trying to figure out how I can apply some AJAX here call to call that method instead. I still need to somehow redirect again back to the same page like I'm doing...I'm doing the redirect in that method after all the logic at the end. I am redirecting again back to the same page, because I need my Page_Load methods in my .aspx and also in an .ascx to still fire off after that method is completed.
So I am not sure where to start on this. Let me go through this once again:
Custom control has a repeater in it and in the repeater, each item has a standard HTML hyperlink (non ASP.NET control) which wraps a standard image tag (image is a button)
User control contains the custom control
The .aspx page contains the user control
User clicks the button and hyperlink redirects them to the parent .aspx page that is using this custom control...so it calls Response.Redirect(Request.Path)
In the code-behind of this .aspx, in my page_load I check a querystring flag to see if I performed that action..meaning user clicked that button. For example one of the querystring params is "AddItem" and another querystring param is "itemID". If movedItem is true, then I fire off a method called MoveItem(int itemID)
Method MoveItem is called
Method MoveItem redirects again back to this same .aspx using Response.Redirect(Request.Path).. this is so that the page load is hit again as well as my .ascx page load is hit. Because in both those page loads, I rebind a repeater so I can show the latest state of the lists. I call a method in my .aspx page_load which rebinds a grid and then page_load in my .ascx also calls another method which rebinds some other list
You can use $.get() to pass the variables to a server-side method that performs any server-side functions you need. You don't need to run page_load or have a code behind.
If you only need to update the HTML in the client's browser then you can use jQuery to add/remove them from the lists in the HTML. You can use the html() function in jQuery to append the item to the list.
You should look at DataTables.net as you can build a client side, editable grid that will perform Ajax updates as well. You would be able to keep your repeater control, but eliminate all the back and forth to the server and the deciphering of clicks and coordinating between Page_Load and etc. Here is a good post from Dave Ward(Encosia) that covers jQuery, Page_Methods and repeater controls.
If you want to preserve your work so far, why not try Ajax Update Panels around the region that you do not want to visible "refresh"?
Remember that the first A of AJAX is asynchronous. You'll want to avoid having your button reload the page, of course. Something like:
Figure out the data you need to send to your "add to shopping cart" handler page -- part number (SKU, etc.), colors, sizes, quantity, etc.
Ensure this data is on every applicable page, in an identical fashion: perhaps one or more hidden input elements, or even from the page URL.
Replace the custom control hyperlink/button href with a [client side] onclick handler instead, which will get the data from step 2 and send it via $.ajax() (or $.post or $.get), specifying the response handlers. You probably want to disable the button or give other visual feedback to avoid duplicate clicks.
In the response handlers, update the shopping cart section of the page with the number of items or indicate success or failure.

Page refresh and bind not working

I've got a .aspx and in it an .ascx. In the .ascx I have a server control.
The .aspx has a list of items in a cart
The .ascx has a list of some cross-sell items (fed from a custom server control) that the customer can add to the cart if desired
both the list of items in cart and list of cross sell items are driven by a repeater and bound on page load. So the .aspx calls a method that rebinds the cart items on page load. And the .ascx calls a method in its page load that rebinds the cross sell items in that custom control (.cs) that is in my .ascx.
The problem I have is, when the user clicks a "add to cart" button in the repeater inside my custom control, the page refreshes and what should happen is the cart items in the .aspx AND the list of cross sells should refrsh showing that the cross sell item was moved to the cart. But even though when I debug and I see the list being rebound with the corret # of items after the move, the page still shows the old state. I have to refresh the page manually again to get it to work.
I guess I need to check for Page.IsPostback? but even if I don't check that..at the least both lists should be refreshing regardless cause I have it in my page load. So even if it's a postback, and I'm not checking for that the lists should show the new state because I'm not even checking for postback anyway. So checking for postaback I don't think is the issue here cause i want the lists to rebind and re-update on any page load....initial or if it's a postback...it doesn't matter. Reload every time. But it doesn't seem to be doing this even though I clearly see the revbind of the lists having the right count (one less on the cross sell and one additional to the cart as it was added after the user clicked the button).
So lets recap again. Here's the sequence of events:
User is on their cart page
User sees a list of cart items that they have added to their cart already (this list is bound in the Cart.aspx and rebound on every page load)
User sees a list of possible cross sell items they can add to their cart somewhere on the page. This list is a custom control found in my .ascx and that .ascx is obviously in my .aspx. The custom control is just a repeater that lists out the cross sell items
User clicks one of the "Add to cart" buttons on one of the cross sells
Page refreshes. In the page load of the .aspx AND the .ascx, I am going out to the DB and rebinding both those lists based on the new state...that is, the new lists after the item was added to the cart which means that now the cart items should have one more added to the list and it does...I clearly see that the new list has one more.
The page comes back after the refresh but I don't see the lists reflecting the new state...I don't see the new item in the cart items list and the added cross sell removed from the cross sell list even though again both lists when I debug are showing correct set of records reflecting the new state
so I'm lost here as to why this is not showing me the updated results.
The problem is, that the eventhandler for the "add to cart" button is called after the page_load. That means that the old items are bound.
The solution would be to manually force a .DataBind() in the eventhandler.
Nevertheless, I would recommend to stay at
if(!Page.IsPostBack)
{
// bind cart
}
in the Page_Load to avoid multiple binds.
Ok, since my Add to cart button is just a hyperlink and the user control checks for a flag in the querystring to fire off a method that moves the item (it gets the item # in the querystring as well to move), I just did a redirect (Response.Redirect(Request.Path);) after the move to cart to the parent .aspx page. That way it will hit the page load for both the cart.aspx and myusercontrol.ascx and rebind the grids.

Event handling in Dynamic asp.net user Control

I have a page, where I want to dynamically add asp.net user controls.
The scenario is that we want that on specific event of a control, It disposes itself and loads another control in the page.
I am not able to have solution about how to do this?
Anyone have decent idea?
Let's assume this scenario:
You have a shopping cart page.
The shipment control is loaded.
The user clicks on the next button.
--- Postback ---
The shopping cart page is loaded
The shipment control is loaded.
The event 'click' is handled by the shipment control.
The shipment control is disposed.
The payment control is loaded.
You can store a variable in the Session instance to determine which control needs to be loaded.
In the PageInit of the shopping cart page you retrieve the Session variable and load the corresponding control (step 1 & 2).
Make sure you do this in the PageInit in order for ASP.NET to fire the events.
In the event handler in the shipment control, you then update the Session variable (step 3).
In the Page_LoadComplete of the shopping cart page you dispose the shipment control (step 4) and load the payment control (step 5).
Scott Mitchell has written a great article about this scenario: http://scottonwriting.net/sowBlog/posts/3962.aspx
Webforms or ASP.NET MVC? I'll assume webforms...
Try using a CompositeControl. If there is databinding involved you can use the DataBoundCompositeControl. In the CreateCHildren method you dynamically create your controls add add them to the child collection. Here is an example of a fairly complicated DataBoundCompositeControl I created once (with event handling on inner child controls):
Scaffolding Control
This is actually a really hard thing to get right. Just remember to rebuild all of your child controls everytime and to store the state of the control so you can recreate everything properly.
You will rebuild everything twice on postbacks (and once on the first GET). Once to recreate the controls to their previous state and the second time to process the changes after databinding and event handling.

Resources