ASP.NET: rendering content after master is already rendered - c#

I have a button on a content page which is suppose to modify the value of a textbox on the master page. The setup is simple enough.
Content Page - Code Behind - Button Click Handler:
protected void but_mybutton_Click(object sender, EventArgs e)
{
string new_value = "!!";
Master.textbox_value(new_value);
}
The problem is that by the time it get to that function, the master's page is already rendered. To get the new value to display, I would need to re-fresh the page. Is there anyway to explicitly tell a page to re-render because I have changed some values on it's controls without having to re-fresh the page?

The master page renders indeed like it's a control on the page.
This blogpost shows you the full page life cycle including the events of the master page.
http://weblogs.asp.net/ricardoperes/archive/2009/03/08/asp-net-page-events-lifecycle.aspx
From the code you have provided this should work as the OnClick handler of the button gets executed before the OnPreRender of the masterpage. Can you show us the code of what
Master.textbox_value(new_value);
does?
I just tested this with the most simple setup. On the masterpage 1 label and a method that sets the text of the label.
public partial class SiteMaster : System.Web.UI.MasterPage
{
protected void Page_Load(object sender, EventArgs e) {}
public void SetLabelText(string text) {
this.Label1.Text = text;
}
}
On the content page a button. The onclick handler of the button calls the method on the masterpage.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) {}
protected void Button1_Click(object sender, EventArgs e)
{
((SiteMaster)this.Master).SetLabelText("foo");
}
}
This sets the text of the label in the same postback as expected.

You will need to review the ASP.NET Page Life Cycle to get a better understanding of how the events are firing.
Your best bet is to try setting the value on the page OnInit or LoadViewstate events.

Related

From UserControl page, Call Page_Prerender in Parent page

I have a aspx page name MakeRedemption.aspx, in which have a UserControl (Search.ascx).
There is Page_Prerender() in the MakeRedemption.aspx.
I would like to ask, how can I call the Page_Prerender() from MakeRedemption.aspx, by a function in Search.ascx.
It is something as follow :
Actually there is a looping in one of the function in my User Control page.
The Page_Prerender (MakeRedemption.aspx) will trigger after all the loop finish.
What I want is :
Everytime before end of each itme of the loop, I will like to trigger the Page_Prerender on the MakeRedemption.aspx to do something.
Something like :
for (int i = 0 ; i < 10 ; i ++)
{
//some code here
// I would like to trigger Page_Prerender here to do something before end of the loop.
} // the Page_Prerender (in MakeRedemption.aspx) trigger after all the loop finish.
Means that, this for loop has i = 10, thus, I would like to trigger the Page_Prerender 10 times inside the for loop.
My PreRender function in the aspx file is as follow :
protected void Page_Prerender(object sender, EventArgs e)
{
//some code here
}
Not sure this Page_Prerender() is consider as the auto generate OnPreRender() or not.
I would like to trigger this Page_Prerender() instead of OnPreRender() .
Sorry if I am asking a stupid question, I am new in programming and c#.
Kindly advise.
Thanks.
Finally i find the way to do it, the oodng is as follow :
Add this following code in the aspx.cs page:
delegate void DelMethodWithoutParam();
protected void Page_Load(object sender, EventArgs e)
{
DelMethodWithoutParam delParam = new DelMethodWithoutParam(Page_prerender);
this.ucSearchGifts.PageMethodWithNoParamRef = delParam;
}
Page_prerender(){
//some code here...
}
and add this following code in the user control cs page:
private System.Delegate _delNoParam;
public Delegate PageMethodWithNoParamRef
{
set { _delNoParam = value; }
}
protected void Button1_Click(object sender, EventArgs e)
{
_delNoParam.DynamicInvoke();
}
When click on the Button1 in user control page, the Page_prerender() in aspx page, which is parent page, will be trigger.

Run the button event handler before page_load

I have a table with all the objects I have in my db. I load them in my Page_Load function. I have a text field and a button that when clicking the button, I want the handler of that click to put a new object with the name written in the text field in the db.
Now, I want that what happens after the click is that the page loads again with the new item in the table. The problem is that the button event handler is run after the Page_Load function.
A solution to this would be to use IsPostBack in the Page_Load or use the pre load function. A problem is that if I would have 3 different buttons, I would have to differ between them there instead of having 3 different convenient functions.
Any solutions that don't have this problem?
Code:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["userId"] == null)
Response.Redirect("Login.aspx");
// LOAD DATA FROM DB
}
protected void CreateObject(object sender, EventArgs e)
{
// SAVE THE NEW OBJECT
}
Maybe you should try loading your data during PreRender instead of Load
protected void Page_Load(object sender, EventArgs e)
{
this.PreRender += Page_PreRender
if (Session["userId"] == null)
Response.Redirect("Login.aspx");
}
protected bool reloadNeeded {get; set;}
protected void CreateObject(object sender, EventArgs e)
{
// SAVE THE NEW OBJECT
reloadNeeded = true;
}
protected void Page_PreRender(object sender, EventArgs e)
{
if(reloadNeeded || !IsPostBack)
// LOAD DATA FROM DB
}
You can check the event target and do what you need then:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
string eventTarget = Page.Request.Params["__EVENTTARGET"];
if(whatever)
{
//do your logic here
}
}
}
Get control name in Page_Load event which make the post back
Use the Page_PreRenderComplete event to retrieve your table. That way your page will always have the most recent data available after all user events have fired.
Why don't you move what you have in the click event into a new method. Then call that method as the first line in your page load?
An old question but I faced the same problem in my C#/ASP.NET Website with master/content pages: a click on a link on the master page should change a query parameter for a gridview on the content page. As you stated the button click event is handled after Page_Load. But it is handled before Page_LoadComplete (see the information about ASP.NET Page Life Cycle), so you can change the page content there.
In my case I solved the problem by setting a session variable in the click event in the master page, getting this variable in the Page_LoadComplete event in the content page and doing databind based on that.
Master page:
<asp:LinkButton ID="Btn1" runat="server" OnCommand="LinkCommand" CommandArgument="1" >Action 1</asp:LinkButton>
<asp:LinkButton ID="Btn2" runat="server" OnCommand="LinkCommand" CommandArgument="2" >Action 2</asp:LinkButton>
protected void LinkCommand(object sender, CommandEventArgs e)
{
HttpContext.Current.Session["BindInfo", e.CommandArgument.ToString());
}
Content page:
protected void Page_LoadComplete(object sender, EventArgs e)
{
string BindInfo = HttpContext.Current.Session["BindInfo"].ToString();
YourBindDataFunction(BindInfo);
}

How do I attach an event handler to an ASP.NET control created at runtime?

Good morning everybody.
I have a question connected with controls and event handling. Lets say I want to create a LinkButton.
protected void loadLinkButton()
{
ContentPlaceHolder content = (ContentPlaceHolder)this.Master.FindControl("MainContent");
LinkButton lnk = new LinkButton();
lnk.ID = "lnikBtn";
lnk.Text = "LinkButton";
lnk.Click += new System.EventHandler(lnk_Click);
content.Controls.Add(lnk);
}
Here is the event handler:
protected void lnk_Click(object sender, EventArgs e)
{
Label1.Text = "ok!";
}
If I run the loadLinkButton function inside Page_Load everything is ok. But when I try to run the loadLinkButton by clicking simple button, link button is created but event is not handled.
protected void Button1_Click(object sender, EventArgs e)
{
loadLinkButton();
}
I there any way to solve it? Or loadLinkButton must always regenerated on Page_Load, Page_init etc.
When working with dynamic controls, I always add the control in Page_Init, because viewstate loading will happen right after Init. If you add it to Page_Load, there is a chance that you will lose viewstate. Just make sure you provide a unique control ID.
It is important to know how ASP.Net determines which events to invoke. The source of each event is passed using a hidden field:
<input type="hidden" name="__EVENTTARGET" value="" />
Whenever the page loads, it pulls in the source of the event from that field and then determines which event to invoke. Now this all works great for controls added through markup because the entire control tree is regenerated on every request.
However, your control was only added once. When a Postback occurs, your control no longer exists as a Server control in the tree, and therefore the event never fires.
The simply way to avoid this is to make sure your Dynamic Controls are added every time the page loads, either through the Page_Init event, or the Page_Load event.
You are right. This is the expected behavior. Page_Load and Page_Init would be the events where you should be adding it.
That would be because when you click your dynamically generated linkbutton, you do a postback to the server. There you do an entirely new pageload, but your original buttonclick (that generates the link) never happened now, so the linkbutton is never made, and the event can not be thrown.
An alternative is to add the linkbutton you add dynamically, to your page statically, with Visible = false. And when you click the other button, make it visible.
I am not exactly sure what problem you are facing but you should put the dynamic controls code in Page_Init as suggested by #johnofcross:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Page_Init(object sender, EventArgs e)
{
CreateControls();
}
private void CreateControls()
{
var lb = new LinkButton();
lb.Text = "Click Me";
lb.Click += lb_Click;
ph.Controls.Add(lb);
ph.DataBind();
}
void lb_Click(object sender, EventArgs e)
{
lblMessage.Text = "Button is clicked!";
}
}

to avoid page refresh during button click event in asp.net

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack) // If page loads for first time
{
Session["update"] = Server.UrlEncode(System.DateTime.Now.ToString()); // Assign the Session["update"] with unique value
//=============== Page load code =========================
//============== End of Page load code ===================
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Session["update"].ToString() == ViewState["update"].ToString()) // If page not Refreshed
{
//=============== On click event code =========================
Label1.Text = TextBox1.Text;
//lblDisplayAddedName.Text = txtName.Text;
//=============== End of On click event code ==================
// After the event/ method, again update the session
Session["update"] = Server.UrlEncode(System.DateTime.Now.ToString());
}
else // If Page Refreshed
{
// Do nothing
}
}
protected override void OnPreRender(EventArgs e)
{
ViewState["update"] = Session["update"];
}
}
This is not working for high resolution gradient background.
Consider wrapping your button and the label in an updatepanel control, which uses AJAX to refresh their contents.
The rest of the page will not be reloaded and the action will not affect the browser navigation.
See this page on how an updatepanel control works.
Since you are handling the button click event in server side there has to be a postback to handle it.
If you do not want a post back to happen change the event handling to "client click"
//Heinzi code worked for me just made a small change in OnPreRender event, assign the ViewsState value when its not post back
protected override void OnPreRender(EventArgs e)
{
if (!IsPostBack)
{
ViewState["update"] = Session["update"];
}
}

How do I dynamically create/remove controls, with EventHandlers, to/from an ASP.NET page?

In one of my projects I need to build an ASP.NET page and some of the controls need to be created dynamically. These controls are added to the page by the code-behind class and they have some event-handlers added to them. Upon the PostBacks these event-handlers have a lot to do with what controls are then shown on the page. To cut the story short, this doesn't work for me and I don't seem to be able to figure this out.
So, as my project is quite involved, I decided to create a short example that doesn't work either but if you can tweak it so that it works, that would be great and I would then be able to apply your solution to my original problem.
The following example should dynamically create three buttons on a panel. When one of the buttons is pressed all of the buttons should be dynamically re-created except for the button that was pressed. In other words, just hide the button that the user presses and show the other two.
For your solution to be helpful you can't statically create the buttons and then use the Visible property (or drastically change the example in other ways) - you have to re-create all the button controls dynamically upon every PostBack (not necessarily in the event-handler though). This is not a trick-question - I really don't know how to do this. Thank you very much for your effort. Here is my short example:
From the Default.aspx file:
<body>
<form id="form1" runat="server">
<div>
<asp:Panel ID="ButtonsPanel" runat="server"></asp:Panel>
</div>
</form>
</body>
From the Default.aspx.cs code-behind file:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace DynamicControls
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
AddButtons();
}
protected void AddButtons()
{
var lastClick = (string) Session["ClickedButton"] ?? "";
ButtonsPanel.Controls.Clear();
if (!lastClick.Equals("1")) AddButtonControl("1");
if (!lastClick.Equals("2")) AddButtonControl("2");
if (!lastClick.Equals("3")) AddButtonControl("3");
}
protected void AddButtonControl(String id)
{
var button = new Button {Text = id};
button.Click += button_Click;
ButtonsPanel.Controls.Add(button);
}
private void button_Click(object sender, EventArgs e)
{
Session["ClickedButton"] = ((Button) sender).Text;
AddButtons();
}
}
}
My example shows the three buttons and when I click one of the buttons, the pressed button gets hidden. Seems to work; but after this first click, I have to click each button TWICE for it to get hidden. !?
I think that you have to provide the same ID for your buttons every time you add them like this for example (in first line of AddButtonControl method):
var button = new Button { Text = id , ID = id };
EDIT - My solution without using session:
public partial class _Default : Page
{
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
AddButtons();
}
protected void AddButtons()
{
AddButtonControl("btn1", "1");
AddButtonControl("btn2", "2");
AddButtonControl("btn3", "3");
}
protected void AddButtonControl(string id, string text)
{
var button = new Button { Text = text, ID = id };
button.Click += button_Click;
ButtonsPanel.Controls.Add(button);
}
private void button_Click(object sender, EventArgs e)
{
foreach (Control control in ButtonsPanel.Controls)
control.Visible = !control.Equals(sender);
}
}
You need to make sure that your dynamic controls are being added during the Pre_Init event.
See here for the ASP.NET Page Lifecycle: http://msdn.microsoft.com/en-us/library/ms178472.aspx
When adding events you need to do it no later than the Page_Load method and they need to be added every single request, ie you should never wrap event assignment in a !IsPostBack.
You need to create dynamic controls ever single request as well. ViewState will not handle the recreation on your behalf.
One thing I notice is that when you click a button you are invoking AddButtons() twice, once in the Page_Load() and once in the button_Click() method. You should probably wrap the one in Page_Load() in an if (!IsPostBack) block.
if (!IsPostBack)
{
AddButtons();
}
AFAIK, creating of controls should not be placed in Page_Load but in Page_PreInit (ViewState and SessionState is loaded before Page_Load but after Page_PreInit).
With your problem, I would suggest to debug the AddButtons function to find out what exactly (and when) is stored in Session["ClickedButton"]. Then, you should be able to figure out the problem.
the controls that are added dynamically are not cached so this migth me one of your problems

Categories

Resources