UpdatePanel where Button Event does not fire - asp.net

I have a UpdatePanel with a PlaceHold contained in it. I create some controls with Labels and Buttons, when Button is clicked it fires an Event that clears PlaceHolder and adds some Textboxes and a Button with an Event.
Problem is when this Button is click it appears to do a PostBack and does not fire Event associated with Button. I thought that since these controls are all contained within the UpdatePanel the would be no PostBack, am I missing the flow.
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<%--<%# Register assembly="System.Web.DynamicData, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" namespace="System.Web.DynamicData" tagprefix="cc1" %>
--%>
<div id="content" > <!--start content div-->
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<br />
<asp:UpdatePanel ID="upBlog" runat="server" UpdateMode="Conditional">
<ContentTemplate >
<asp:PlaceHolder ID="phBlog" runat="server"></asp:PlaceHolder>
</ContentTemplate>
<Triggers >
<%-- <asp:AsyncPostBackTrigger EventName="Click" ControlID = "btnSave" />--%>
</Triggers>
</asp:UpdatePanel>
<br />
</div> <!--ends content div-->
</asp:Content>
//Code Behind
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
FirstView();
}
protected void Page_Load(object sender, EventArgs e)
{
}
private void FirstView()
{
FileStream fs = new FileStream(Server.MapPath(GlobalVar.compathver), FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
DataSet dset = new DataSet();
dset.ReadXml(fs);
fs.Close();
//other controls
Button btnComments = new Button();
btnComments.ID = "mybtnComments" + i.ToString();
btnComments.BorderWidth = 0;
btnComments.Text = MyFunc.CountComments(row["ID"].ToString(), dset) + " Comments";
phBlog.Controls.Add(btnComments);
btnComments.CommandArgument = row["ID"].ToString();
btnComments.BorderWidth = 0;
btnComments.Command += new CommandEventHandler(Button1_Click)
}
private void CommentView(string ID) /// THIS DOES not FIRE
{
DataView myCommentView = GetCommentView(ID);
Button btnCommentSave = new Button();
btnCommentSave.ID = "mySavebtnComments" + i.ToString();
btnCommentSave.Text = "Publish";
btnCommentSave.BackColor = Color.Aquamarine;
phBlog.Controls.Add(btnCommentSave);
btnCommentSave.CommandArgument = row["ID"].ToString();
btnCommentSave.Click += new EventHandler(btnSave_Click);
}
protected void Button1_Click(object sender, CommandEventArgs e)
{
CommentView(e.CommandArgument.ToString());
}
protected void btnSave_Click(object sender, EventArgs e)
//protected void btnSave_Click(object sender, CommandEventArgs e)
{
FileStream fsxml = new FileStream(Server.MapPath(GlobalVar.compathver), FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite);
//other code
// XML Document Saved
xmldoc.Save(fsxml);
}

The UpdatePanel still does a postback. The whole page life-cycle is repeated when the button is clicked, and therefore the Page_Init and Page_Load for example will be executed again. AJAX does not remove the postbox, just hides it from the client.
I can't obviously see something wrong with the code you've posted however I would suggest you place a break point in the Page_Init as a start. This will be able to tell you if the postback is actually happening or not, since this will be fired if the button is indeed trying to fire the button click event. Keep in mind any click events is fired after the page life cycle completes (Theoretically).
On second look I would suggest that you change the Button event in the FirstView() method to a Click rather then a Command and see if this triggers the event.

it is better to add any event to the control before adding the control to another container.
secondly the button with the parameter name "btnCommentSave" will not work. You have to be careful on OnInit, OnLoad events. It is server-client side issue. The page pushed from server to client does not include the "btnCommentSave" button, so that this button stays at the clients page but it does not work.
btnComments works, because it is rendered by server before pushing to client at UpdatePanel's OnLoad function.
What rendered after OnLoad functions, does not work.

Related

How do I load two ASP.NET UserControls on Demand?

I want load two user controls on demand.
asp:UpdatePanel ID="UpdatePanel1" runat="server"
ContentTemplate
asp:Button ID="Button1" runat="server" Text="Button" UseSubmitBehavior="false"
OnClick="Button1_Click" /
div id='Div_UserControlPlace' enableviewstate="true" runat="server"
/div
/ContentTemplate
Triggers
asp:PostBackTrigger ControlID="Button1" /
/Triggers
/asp:UpdatePanel
asp:UpdatePanel ID="UpdatePanel2" runat="server"
ContentTemplate
asp:Button ID="Button2" runat="server" Text="Button" UseSubmitBehavior="false"
OnClick="Button2_Click" /
div id='Div_UserControlPlace2' enableviewstate="true" runat="server"
/div
/ContentTemplate
aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
Control FeaturedProductUserControl = new Control();
FeaturedProductUserControl = LoadControl("WebUserControl1.ascx");
FeaturedProductUserControl.EnableViewState = true;
Div_UserControlPlace.Controls.Add(FeaturedProductUserControl);
}
protected void Button2_Click(object sender, EventArgs e)
{
Control FeaturedProductUserControl2 = new Control();
FeaturedProductUserControl2 = LoadControl("WebUserControl2.ascx");
FeaturedProductUserControl2.EnableViewState = true;
Div_UserControlPlace2.Controls.Add(FeaturedProductUserControl2);
}
I load the first user control by clicking on the first button - this works properly but when I click on the other button to load the second UserControl, the first UserControl disappears and the second UserControl loads.
Thanks
IFA_User
You should use the Placeholder control to dynamically add your controls to the form.
Take a look at my last responses about dynamic controls:
OnClick event of dynamically created LinkButtons is not working
Dynamically Added DropDownlists Are Not Firing SelectedIndexChanged Event
Dynamically create an ImageButton
Now I already have some code working for demo purpose, each dynamic user controls keeps its state across post backs
This is the output:
ASPX
<asp:PlaceHolder runat="server" ID="addresses" /><br />
<asp:Button Text="Add Address" runat="server" ID="addAddress" OnClick="addAddress_Click" />
ASPX Code behind
protected void Page_PreLoad(object sender, EventArgs e)
{
for (int i = 0; i < this.DynamicControlsCount; i++)
{
var c = this.LoadControl("~/AddressControl.ascx");
this.addresses.Controls.Add(c);
}
}
protected void addAddress_Click(object sender, EventArgs e)
{
this.DynamicControlsCount++;
var c = this.LoadControl("~/AddressControl.ascx");
this.addresses.Controls.Add(c);
}
protected int DynamicControlsCount
{
get
{
if (this.ViewState["ac"] == null)
{
return 0;
}
return (int)this.ViewState["ac"];
}
set
{
this.ViewState["ac"] = value;
}
}
ASCX
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="AddressControl.ascx.cs" Inherits="WebApplication1.AddressControl" %>
<asp:Panel ID="Panel1" runat="server" GroupingText="Address" DefaultButton="btnSave">
Street: <asp:TextBox runat="server" ID="txtStreet" /><br />
City: <asp:TextBox runat="server" ID="txtCity" /><br />
<asp:Button Text="Save" runat="server" ID="btnSave" OnClick="btnSave_Click" />
</asp:Panel>
<asp:Panel runat="server" GroupingText="Address Summary" Visible="false" ID="summary">
<asp:Label ID="lblStreet" runat="server" /><br />
<asp:Label ID="lblCity" runat="server" />
</asp:Panel>
ASCX Code behind
protected void btnSave_Click(object sender, EventArgs e)
{
this.summary.Visible = true;
this.lblCity.Text = "Selected city: " + this.txtCity.Text;
this.lblStreet.Text = "Selected street: " + this.txtStreet.Text;
}
When a user control is created in the HTML, asp.net will persist across postbacks without any user interaction. But if you are loading them programatically (dynamically), they will not persist accross postbacks. So if you load them programmatically, you have the added task of persisting them programmatically as well. Use the ViewState (or Session I suppose) to store what has been loaded and perhaps any other necessary information that needs to be loaded between postbacks. Every single postback will require you to reload every control or else they will disappear.
There are couple of ways of doing it:
U can load the UserControls using Ajax. Benefit of using Ajax, is ur page does not get post back, thus for example, on click event of Button1, call a ajax(traditional/Jquery) to load UserControl1, and on button click of Button2 User control2.
Put the two button in two different updated panel, by doing this the click event will only refresh a part of ur page.
U have to save somewhere (ViewState/Session),which buttons are clicked, and upon clicking of any button check the value of that variable, and explicit load the control.
Points to note - If u want to get ur data back when ur page made a complete postback, then u have to add the controls keeping in mind the Page load event cycle.

FindControl() return null

I trying to create application whad add controlls dynamicaly. I have masterpage, my asp:Content is here:
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<asp:ScriptManager ID="scriptManager1" runat="server">
</asp:ScriptManager>
<div style="margin: 10px">
<asp:UpdatePanel ID="updatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="myPlaceHolder" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnAdd" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
<asp:Button ID="btnAdd" runat="server" Text="Add" />
After click in btnAdd I want to add two textboxes. I trying do it like in http://jagdeepmankotia.wordpress.com/2010/01/30/dynamically-add-controls-in-asp-net-c/
This is my code:
static int myCount = 1;
private TextBox[] color;
private TextBox[] text;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
color = new TextBox[myCount];
text = new TextBox[myCount];
for (int i = 0; i < myCount; i++)
{
TextBox tbColor = new TextBox();
tbColor.ID = "colorTextBox" + i.ToString();
myPlaceHolder.Controls.Add(tbColor);
color[i] = tbColor;
TextBox tbText = new TextBox();
tbText.ID = "textTextBox" + i.ToString();
myPlaceHolder.Controls.Add(tbText);
text[i] = tbText;
LiteralControl literalBreak = new LiteralControl("<br />");
myPlaceHolder.Controls.Add(literalBreak);
}
}
public Control GetPostBackControl(Page page)
{
Control control = null;
string ctrlname = page.Request.Params.Get("__EVENTTARGET");
if (ctrlname != null && ctrlname != string.Empty)
{
control = page.FindControl(ctrlname);
}
else
{
foreach (string ctl in page.Request.Form)
{
Control mycontrol = page.FindControl(ctl);
if (mycontrol is System.Web.UI.WebControls.Button)
{
control = mycontrol;
// This gives you ID of which button caused postback
break;
}
}
}
return control;
}
protected void Page_PreInit(object sender, EventArgs e)
{
Control myControl = GetPostBackControl(this.Page);
if (myControl != null)
if (myControl.ClientID.ToString() == "btnAdd")
myCount = myCount + 1;
}
protected void btnAdd_Click(object sender, EventArgs e)
{
//handled in PreInit
}
When in function GetPostBackControl() in loap foreach looking for my btnAdd, for example in first iteration for ctr "ctl00$MainContent$scriptManager1", myControl is null... In next iterations also... So my function always return null. What can be reason?
FindControl only searches direct children of the container. Since you are starting off at the page level, you will need to recurse through the child UpdatePanel control to get to your btnAdd control.
Have a look here for an example how to do do this.
Edit:
I'm not sure I understand why you are 'looking' for your button in this manner, since there is only one static button on the screen - you wouldn't need to use FindControl in this case.
<asp:Button ID="btnAdd" runat="server" Text="Add" onclick="btnAdd_Click" />
(or in code, btnAdd.OnClick += new EventHandler(btnAdd_Click);)
Even if you had multiple Buttons in your form added dynamically, you could wire ALL of them up to the same Button Click handler, in which case sender would then contain the Button Control which was clicked. You would typically use FindControl to scrape the data out of the dynamically added Input controls (text box etc), rather than to see which control caused the Postback (as 'sender' in an appropriate event handler would be easier)
Edit 2:
You can add the buttons dynamically just like your other controls
Button myButton = new Button();
myButton.Text = "Click Me";
myButton.Click += new EventHandler(btnAdd_Click);
myPlaceHolder.Controls.Add(myButton);
If you want all the controls that you've added already to 'stay' in between postbacks then enable viewstate on the page and on the controls, and then make sure that you only add the controls once without postback, in OnInit:
base.OnInit(e);
if (!IsPostBack)
{ // ... Add controls here
You can keep the state of 'mycount' in a hidden field (in the same updatepanel, and with viewstate enabled) - you'll need to parse it to an int each time. Or you can use SessionState to track it.

Can I put a Timer in Ajax updatePannel in a masterpage?

I made a very simple pannel updating wich will query a database and show a message on masterpage through a label.
Thus, I've put an updatePannel with a label and a timer within (obviously with a scriptManager) in my site's masterpage.
However, when I try to interact with the timer1 object, I receive an error message: "object not set to an instance of an object". I not receive this message when placing the schema in a blank page (without masterpage).
I must to run the query in masterpage because the users need to receive information whatever they are in my site.
How can I correctly place the components to do this work? what I'm doing wrong?
Thanks!
I just tried it within a master page without a problem. Here is the relevant code:
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" />
<asp:UpdatePanel ID="updMessage" runat="server">
<ContentTemplate>
<asp:Label ID="lblMessage" runat="server" />
<asp:Timer ID="tmrMessage" Interval="5000" ontick="tmrMessage_Tick" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
From master page code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["Message"] = 1;
}
}
protected void tmrMessage_Tick(object sender, EventArgs e)
{
int message = (int)Session["Message"];
lblMessage.Text = message.ToString();
Session["Message"] = ++message;
}
The problem was where I was putting the panel, label and timer. I put in contentPlaceHolder, where the problem occours. Now I put the control in the form tag, then the problem is solved.

ASP.NET - Update panel in Master page, refresh button in Content Page

I have Update panel in Master page:
<asp:ScriptManager id="CartScript" runat="server"></asp:ScriptManager>
<asp:UpdatePanel id="CartBox" runat="server" updateMode="Conditional">
<ContentTemplate>
Košík [ <asp:HyperLink NavigateUrl="~/Account/Login.aspx" ID="ShoppingCart" runat="server" text="" /> ] <asp:LinkButton ID="DeleteCart" runat="server" Text="Vymazat košík" OnClick="ThrowCart_Click" />
</ContentTemplate>
</asp:UpdatePanel>
and Buy Button in Content page:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Button ID="BuyButton" Runat="server" Text="Přidat do košíku" onclick="Buy_Click" />
</asp:Content>
So I need add to Update panel AsyncPostBackTrigger for this button.
First i tryed add it from content page:
protected void Page_Load(object sender, EventArgs e)
{
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = "BuyButton";
UpdatePanel panel = (UpdatePanel)Master.FindControl("CartBox");
if (panel != null)
{
panel.Triggers.Add(trigger);
}
ScriptManager script = (ScriptManager)Master.FindControl("CartScript");
script.RegisterAsyncPostBackControl(BuyButton);
}
But it did error: A control with ID 'BuyButton' could not be found for the trigger in UpdatePanel 'CartBox'.
So i tried it add from Master page:
protected void Page_Load(object sender, EventArgs e)
{
if ((Button)MainContent.FindControl("BuyButton")!=null)
{
AsyncPostBackTrigger trigger = new AsyncPostBackTrigger();
trigger.ControlID = ((Button)MainContent.FindControl("BuyButton")).ID;
CartBox.Triggers.Add(trigger);
CartScript.RegisterAsyncPostBackControl((Button)MainContent.FindControl("BuyButton"));
}
}
But i got same error. :-(
So can u tell me how I can add to my Update Panel that Button from Content Page can refresh it?
Edit
Place the BuyButton button inside of its own UpdatePanel as well on the content page. Add your AsyncPostBackTrigger to that new UpdatePanel, and then it will be able to find the button, and will use the ScriptManager from the master page.

UpdatePanel wrapped around a user control

I have a user control which contains some buttons and a placeholder. Those buttons cause controls to be added/removed from placeholder. Everything works fine.
Now I want to put this user control in a page, and wrap it in an updatepanel like so:
<asp:UpdatePanel ChildrenAsTriggers="true" ID="UpdatePanelFoo" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<grid:tablegrid ID="tablegrid_chapters" runat="server" SomeProperty="bar" />
</ContentTemplate>
</asp:UpdatePanel>
When I run the page, it's still doing a full postback when I hit one of the buttons inside the user control. What am I doing wrong, and how can I remedy this?
Update:
protected void Page_Init()
{
ScriptManager scr = ScriptManager.GetCurrent(this.Page);
Response.Write("EnablePartialRendering: " + scr.EnablePartialRendering);
}
Outputs "EnablePartialRendering: true"
Make sure you have EnablePartialRendering=true on your ScriptManager in the page.
Update
It looks like your UserControl has no events to be looking for...you have 2 options here. Move the UpdatePanel inside the UserControl .ascx so it can see the button events as children to rig up or add an event for it to see, to do that try something like this:
public event EventHandler Click;
void btn_del_Click(object sender, EventArgs e)
{
if (NumberOfRowControls > 0)
{
var rowToWhack = panel_rows.Controls.Children().Single(x => x.ID == "myrow" + (NumberOfRowControls - 1));
panel_rows.Controls.Remove(rowToWhack);
NumberOfRowControls--;
}
if(Click != null) Click(this, e);
}
void btn_add_Click(object sender, EventArgs e)
{
var row = NewRow(NumberOfRowControls);
panel_rows.Controls.Add(row);
if(Click != null) Click(this, e);
}
And update the UpdatePanel to be looking for it:
<asp:UpdatePanel ID="UpdatePanelFoo" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<grid:tablegrid ID="tablegrid_chapters" runat="server" SomeProperty="bar" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="tablegrid_chapters" EventName="Click">
</Triggers>
</asp:UpdatePanel>
Make sure you add a ScriptManager as well to the page, otherwise there's no UpdatePanel functionality.

Resources