Issue with dynamically loading a user control on button click - c#

I have a page in which I am loading a user control dynamically as follows:
Default.aspx:
<cc1:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server">
</cc1:ToolkitScriptManager>
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
Default.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
var ctrl = LoadControl("~/UserCtrl1.ascx");
ctrl.ID = "ucUserCtrl1";
PlaceHolder1.Controls.Add(ctrl);
}
Below is the code for UserCtrl1.ascx
<asp:Label ID="Label1" runat="server"></asp:Label>
<asp:Button ID="Button1" runat="server" Text="Button1" OnClick="Button1_Click" />
<br />
<asp:PlaceHolder ID="PlaceHolder2" runat="server"></asp:PlaceHolder>
I am dynamically loading another user control when the Button1 is clicked
UserCtrl1.ascx.cs
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "UserControl - 1 button clicked!";
var ctrl = LoadControl("~/UserCtrl2.ascx");
ctrl.ID = "ucUserCtrl2";
PlaceHolder2.Controls.Add(ctrl);
}
Below is the markup for UserCtrl2.ascx
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="Label2" runat="server"></asp:Label>
<asp:Button ID="Button2" runat="server" Text="Button2" OnClick="Button2_Click" />
</ContentTemplate>
</asp:UpdatePanel>
UserCtrl2.ascx.cs
protected void Button2_Click(object sender, EventArgs e)
{
Label2.Text = "UserControl - 2 button clicked!";
}
After the page loads when I click the Button1 in UserCtrl1 the click event fires and I am able to see the Label1 text. It also properly loads the UserCtrl2, but when I click the Button2 in UserCtrl2 the click event dosent fire and even worse when I click the Button2 twice the UserCtrl2 control dissappears from the page. How can I fix this?

The problem with the second control is that you are loding it only after the click of button 1. But when some other (not button 1 click) postback happens your second control is not loaded.
One of possible fixes is saving some flag (e.g. in ViewState) that will help you to determine if your second control should be loaded (and load in on page load).
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "UserControl - 1 button clicked!";
var ctrl = LoadControl("~/UserCtrl2.ascx");
ctrl.ID = "ucUserCtrl2";
PlaceHolder2.Controls.Add(ctrl);
this.SecondControlLoaded = true; // This flag saves to ViewState that your control was loaded.
}
protected void Page_Load(object sender, EventArgs e)
{
var ctrl = LoadControl("~/UserCtrl1.ascx");
ctrl.ID = "ucUserCtrl1";
PlaceHolder1.Controls.Add(ctrl);
if (this.SecondControlLoaded)
{
var ctrl = LoadControl("~/UserCtrl2.ascx");
ctrl.ID = "ucUserCtrl2";
PlaceHolder2.Controls.Add(ctrl);
}
}

Related

Timer, UpdatePanel and dynamically created buttons

I have an update panel with a div (with runat="server") so I dynamically create and add buttons to it on a timer tick event.
The problem is that when a button is click, the is a postback but the button is gone and the event is not raised.
Here's my aspx page and my c# code behind. Nothing I write in the btn1_click actually occurs.
There's a continue to my question but in order to keep it simple, I would like to understand the above first.
I really need your help and i appreciate it, ty.
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:Timer ID="Timer1" runat="server" Interval="2000" ontick="Timer1_Tick">
</asp:Timer>
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<div id="div1" runat="server"></div>
</ContentTemplate>
</asp:UpdatePanel>
<div id="div2" runat="server">div2</div>
</form>
</body>
and this c# here.
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Timer1_Tick(object sender, EventArgs e)
{
CreateControl();
}
void CreateControl()
{
Button btn1 = new Button();
btn1.ID = "btn1";
btn1.Text = "click me";
btn1.Click += new EventHandler(btn1_Click);
div1.Controls.Add(btn1);
}
void btn1_Click(object sender, EventArgs e)
{
div1.InnerHtml += "btn1 was clicked";
}
}
For dynamically added controls you must add them in every page load event. Otherwise by the time it gets to the click event the are already gone. In this case I would add the button to a session collection of buttons every time you create one, then reload that entire collection on every postback, so it doesn't lose what you've already added. Also, save an int in session that you increment so they dont all have the same ID. IDs should be unique
something like:
protected void Page_Load(object sender, EventArgs e)
{
if(Page.IsPostBack)
{
CreateControls(YourCollectionInSession)
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
CreateControl();
}
void CreateControl()
{
Button btn1 = new Button();
btn1.ID = "btn" + yourSessionID;
btn1.Text = "click me";
btn1.Click += new EventHandler(btn1_Click);
div1.Controls.Add(btn1);
yourSessionID++;
YourCollectionInSession.Add(btn1);
}
void CreateControl(List<Button> buttons)
{
foreach(Button btn in buttons)
{
div1.Controls.Add(btn);
}
}
I've had to do the same thing before and this approach worked for me. Just remember the ASPx Page Lifecycle. It will always hit the page_init and page_load before it handles any post back events, meaning your controls are long gone.

TextChanged doesn't fire

I am trying to generate textboxes when the I press button add more so this is the code for onclick
protected void Add_TextBoxes(object sender, EventArgs e)
{
int index = int.Parse(ViewState["pickindex"].ToString());
TextBox MyTextBox = new TextBox();
MyTextBox.ID = "tbautogenerated"+index.ToString();
MyTextBox.Text = "tbautogenerated" + index.ToString();
MyTextBox.Width= 250;
MyTextBox.MaxLength = 128;
MyTextBox.Attributes.Add("runat", "server");
MyTextBox.CausesValidation = false;
MyTextBox.AutoPostBack = true;
MyTextBox.TextChanged += new EventHandler(MyTextBox_TextChanged);
picktexts.Controls.Add(MyTextBox);
}
void MyTextBox_TextChanged(object sender, EventArgs e)
{
TextBox MyTextBox = sender as TextBox;
}
but when I change in the textbox the textChanged doesn't work !!! what's wrong ?
HTML Code
<asp:UpdatePanel ID="UpdatePanel2" runat="server">
<ContentTemplate>
<div id="picktexts" runat="server">
<asp:TextBox ID="txtAdress" runat="server" MaxLength="128" Width="250" />
<asp:RequiredFieldValidator ControlToValidate="txtAdress" Display="Dynamic" ID="rfvAddress" Text="* Required" runat="server" />
<asp:Button ID="bt_addtxtbox" runat="server" Text="Add more" OnClick="Add_TextBoxes" CausesValidation="false" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
I think the event handlers are getting lost between posts. the way ASP.NET works, every time you post a page back to itself, all objects are instantiated again, and their state is recovered from the ViewState. Normally a control that's declared in the aspx would reassociate itself with events by the declaration in its tag, which is not the case here.
So try associating the event handlers again during the page load. Like this:
void Page_Load (object sender, EventArgs e)
{
foreach (Control c in picktexts.Controls)
{
((TextBox)c).TextChanged += new EventHandler(MyTextBox_TextChanged);
}
}
And see if it works.

How to I carried out Textbox value from ViewState when I postback?

I want to know that how can I trace out the value of Textbox from ViewState.
As user enters any value into Textbox and click submit button because of postback Textbox value disappears ,
But if I used ViewState in this case , then is there any way to see or display that value from Viewstate?
<html>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" /
</form>
</body>
</html>
protected void Button1_Click(object sender, EventArgs e)
{
TextBox1.Text += "X";
}
In your page load use this.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (ViewState["Values"] == null)
{
ViewState["Values"] = new string();
}
}
TextBox1.Text = ViewState["Values"].ToString();
}
After that use this.
protected void Button1_Click(object sender, EventArgs e)
{
ViewState["Values"] += TextBox1.Text;
}
In the first Page_Load method, You will create a ViewState if its not a postback and its null. After that write the textbox your viewstate, in Button1_Click you will add your new textbox1 to your viewstate.

modal pop-up ok button not working as expected for a dropdown menu

CODE BEHIND:
private void Page_Load(object sender, System.EventArgs e)
{
if (!Page.IsPostBack)
{
ddlLanguage.SelectedValue = Thread.CurrentThread.CurrentCulture.Name;
}
}
protected void ddlLanguage_SelectedIndexChanged(object sender, EventArgs e)
{
if (ddlLanguage.SelectedValue == "es-ES")
{
mdlPopup.Show();
}
//Sets the cookie that is to be used by Global.asax
HttpCookie cookie = new HttpCookie("CultureInfo");
cookie.Value = ddlLanguage.SelectedValue;
Response.Cookies.Add(cookie);
//Set the culture and reload the page for immediate effect.
//Future effects are handled by Global.asax
Thread.CurrentThread.CurrentCulture = new CultureInfo(ddlLanguage.SelectedValue);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(ddlLanguage.SelectedValue);
//Server.Transfer(Request.Path);
}
protected void OKButton_Click(object sender, EventArgs e)
{
Server.Transfer(Request.Path);
}
ASPX PAGE:
<asp:DropDownList ID="ddlLanguage" class="langpnl" runat="server" AutoPostBack="True"
OnSelectedIndexChanged="ddlLanguage_SelectedIndexChanged">
<asp:ListItem Value="en-US">Eng</asp:ListItem>
<asp:ListItem Value="es-ES">Esp</asp:ListItem>
</asp:DropDownList>
<ajaxToolkit:ModalPopupExtender ID="mdlPopup" runat="server" TargetControlID="testhidden"
PopupControlID="pnlPopup" OkControlID="OKButton" />
<asp:Panel ID="pnlPopup" runat="server" Width="500px" Style="display: none">
All content may not be in Spanish.
<asp:Button ID="OKButton" runat="server" Text="OK" OnClick="OKButton_Click" />
</asp:Panel>
<asp:HiddenField ID="testhidden" runat="server" />
I am trying to set the language as per the selection in the Dropdown box. But if the user selects spanish I want to display a popup modal with a msg & once the button OK is pressed I want to postback the whole page.
Currently I am able to display the popup but the page never refreshed so the language still doesn't change. In the code behind if I remove the server.transfer from the OK button and put it in the SelectIndexChange then the page postback is working but there is no popup masg .I think the page gets postback after the popup executes so it never gets displayed...please need some help I am breaking my head since last 3 days.
Define another button in that panel... and do whatever you want in his onclick event. So you will have a postback.
The OKButton click event... OKButton_Click will not fire as long as you assigned him in you modalpopup...
if (ddlLanguage.SelectedValue == "es-ES")
{
mdlPopup.Show();
}
else
{
Server.Transfer(Request.Path);
}
& removed the OK button from Modalpopup..finally got to see what I was Expecting..

Getting control value when switching a view as part of a multiview

I have the following code in my aspx page:
<asp:Button id="display_button" runat="server" Text="Display" OnClick="Button1_Click" />
<asp:Button id="edit_button" runat="server" Text="Edit" OnClick="Button2_Click" />
<asp:Button id="save_button" runat="server" Text="Save" OnClick="Button3_Click" Visible="false" />
<asp:MultiView id="MultiView1" runat="server" ActiveViewIndex="0">
<asp:View id="View1" runat="server">
<asp:FormView id="view_program" runat="server">
<ItemTemplate>
<%# Eval("status").ToString().Trim() %>
</ItemTemplate>
</asp:FormView>
</asp:View>
<asp:View id="View2" runat="server">
<asp:FormView id="edit_program" runat="server">
<ItemTemplate>
<asp:DropDownList id="p_status" runat="server">
</asp:DropDownList>
</ItemTemplate>
</asp:FormView>
</asp:View>
</asp:MultiView>
and the following functions attached to the buttons in the code-behind page:
protected void Button1_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View1);
save_button.Visible = false;
}
protected void Button2_Click(object sender, EventArgs e)
{
MultiView1.SetActiveView(View2);
save_button.Visible = true;
}
protected void Button3_Click(object sender, EventArgs e)
{
DropDownList p_status = edit_program.FindControl("p_status") as DropDownList;
var status = p_status.SelectedValue;
Label1.Text = status;
//save_button.Visible = false;
//MultiView1.SetActiveView(View1);
}
The idea being, that there are two views, the first displays the information, if the user wants to edit the information, they click button 2 which changes the view to the edit mode, which has the controls (drop downs, text fields, etc). It also makes the 'save' button appear.
What I am trying to make happen is, when the save button is clicked, it will grab all of the values from the various fields, update the object and then update the database. Then it would flip back to view1 with the updated info.
Problem is, as you can see in void Button3_Click, I try grab the values from the control, p_status, but it only gets the original value. example, the menu has three values, 'Green', 'Yellow', and 'Red'. Green is the default value and is selected when view2 is displayed. However, if I select Yellow or Red, and click save, rather than the label being updated to display one of those two values, it always displays Green.
Any ideas?
edit: page load function per request below
protected void Page_Load(object sender, EventArgs e)
{
try
{
Person myPerson = new Person(userid);
TestProgram myProgram = new TestProgram(id);
List<TestProgram> program = new List<TestProgram> { myProgram };
view_program.DataSource = program;
view_program.DataBind();
edit_program.DataSource = program;
edit_program.DataBind();
DropDownList p_status = edit_program.FindControl("p_status") as DropDownList;
p_status.Items.Add(new ListItem("Green", "Green"));
p_status.Items.Add(new ListItem("Yellow", "Yellow"));
p_status.Items.Add(new ListItem("Red", "Red"));
//myProgram.Status = "Red";
p_status.SelectedValue = myProgram.Status;
}
catch (Exception ex)
{
Response.Write(ex);
Label1.Text = ex.ToString();
}
}
Whoops...missed a little someting.. my
bad
when asp.net is not behaving as expected this is your best friend: MSDN: ASP.NET PAGE LIFECYLE
Upon Further Review...
there are a couple of problems here. your drop down list control with an id of "p_status" is contained inside a multiview (I forgot about what that meant...) you need to move the code to populate p_status into pre-render after checking to see if Multiveiw1.ActiveView = View2. Since it will always be a post back you need to bind values late in the page cycle

Categories