I am using UpdatePanel and loading dynamically the content:
<asp:UpdatePanel runat="server" ID="updatePanel" UpdateMode="Conditional">
<ContentTemplate>
<div id="dashboard-main">
<div id="dashboard-content">
<div class="d-content">
<asp:PlaceHolder runat="server" ID="ContentPanel">
</asp:PlaceHolder>
</div>
</div>
<div id="sub-content">
<ul id="nav-02">
<li class="current">
<asp:LinkButton CommandArgument="Stuff" OnClick="LoadMiniDash" runat="server" ID="myStuff">
My Stuff</asp:LinkButton></li>....
What I do is once the LinkButton is pressed, I load a control to the ContentTemplate:
protected void LoadMiniDash(object sender, EventArgs e)
{
string miniDashName = ((LinkButton)sender).CommandArgument;
Control control = Page.LoadControl("~/controls/Dashboard" + miniDashName + ".ascx");
ContentPanel.Controls.Clear();
ContentPanel.Controls.Add(control);
updatePanel.Update();
}
My problem is, that inside this newly loaded control, there is another Button. once clicked, the updatepanel gets emptied and not postback to the control is made. (it does however do a post to the page itself async. but i see the control won't reach its own code once clicked).
what can be the problem?
thanks
I just tried to rewrite your question. When you load your userControl it appears in the updatePanel. When you hit the button in the userControl, your updatePanel gets updated - and your userControl "disappears".
Imo it disappears because you do not reload your userControl. I tried the following snippet:
protected void btnLoadControl_Click(object sender, EventArgs e)
{
/// save the name of the userControl to load in a SessionVar
Session["userControl2Load"] = "ucDemo.ascx";
Control control = LoadControl("ucDemo.ascx");
phDemo.Controls.Clear();
phDemo.Controls.Add(control);
upDemo.Update();
}
/// reload your userControl on every init of the updatePanel
/// when the sessionVar is set
protected void upDemo_Init(object sender, EventArgs e)
{
if (Session["userControl2Load"] != null)
{
string controlName = Session["userControl2Load"].ToString();
Control control = LoadControl(controlName);
phDemo.Controls.Clear();
phDemo.Controls.Add(control);
}
Debug.WriteLine("upDemo Init");
}
it worked for me. Let me know if it work for you too. hth
I have faced similar issue.. and you know solution to this problem is very simple..
Logic is .. If you have one or more update panel in the same page then properties of all update panel should be same such as
Update Mode : Always
EnableViewState : true(if you are using it)
For example you have 3 update panel in the same asp.net ajax page with following id
UpdatePanel1
UpdatePanel2
UpdatePanel3
In the Update Panel 1 (UpdatePanel1) you have a button which specific a record from the gridview. On the click on the button in the update panel1, FormView in the UpdatePanel2 should display the corresponding values.
To achieve this, you need to specific Update Panel Properties of (UpdatePanel1, UpdatePanel2) as
ChildrenAsTrigger : True
EnableViewState : true
RenderMode : Block/Inline
UpdateMode : Always
Visible : true
Doing above activity values in the UpdatePanel3 is changed or you can say it's not depending on the UpdatePanel1 or UpdatePanel2
If you find it useful, please mark it as your answer else let me know...
Related
I have an AJAX Control Toolkit TabContainer in my ASP.NET page. In one of the tabs in the TabContainer, there is a GridView. Now, I have an UpdatePanel for which I want to give trigger as "RowCommand" of GridView mentioned above. The UpdatePanel is outside the TabContainer. But when I give the GridView id, I am getting the error:
A control with ID 'grvSummary' could not be found for the trigger in UpdatePanel 'updSegment'.
Trigger markup:
<asp:AsyncPostBackTrigger ControlID="grvSummary" EventName="RowCommand" />
You will have to programmatically add the trigger to your UpdatePanel. This is because your GridView may or may not start in a different ContentPlaceHolder than the UpdatePanel (namely, the <ContentTemplate> of your TabContainer). Like this (note that this really needs to be done in Page_Init, due to the Page Life Cycle):
protected void Page_Init(object sender, EventArgs e)
{
AsyncPostBackTrigger trig = new AsyncPostBackTrigger();
trig.ControlID = grvSummary.UniqueID;
trig.EventName = "RowCommand";
updSegment.Triggers.Add(trig);
}
It looks like this may be a problem with ASP.NET / AJAX assuming the wrong Control.UniqueID value for the Control being used as a trigger.
Source: Triggering an UpdatePanel in a different ContentPlaceHolder
MSDN says that create Dynamic Controls in PreInit Event of Page Life Cycle.
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Why?
What advantage is derived by creating in PreInit Event?.
I have seen code where developers are creating dynamic controls in the Page_Load Method?
If there any difference?.
Regards
Page_Load works fine if you don't need to worry about saving the controls' ViewState across postbacks, but if you need to persist it, the Load stage is not where you should add these controls.
Dynamic controls must exist within the page's control hierarchy before the ViewState is loaded. There's only one stage before Load View State - Initialization. That means, if you want your dynamic controls to persist view state you must add them to the control hierarchy in the page's Init event.
https://web.archive.org/web/20210302172017/https://aspnet.4guysfromrolla.com/demos/printPage.aspx?path=/articles/092904-1.aspx
But mind that you cannot access the ViewState in Init event because it's yet not loaded. So you need to use a different persistence medium to store variables across postbacks(like Session) if required.
This reply might be late for the original poster but I thought it might help some other people.
If your application/ website doesn't use master page, it's best to create controls at Page_PreInit event. But if you use master page and want to create controls on content pages at run time Page_Init is the ideal event.
You can also create controls on Page_Load but bear in mind page load is fired after View State is loaded.
Tim,
Thanks for the reply.
I did a small experiment in which I am creating and adding a TextBox control dynamically in Page_Load method.
In the Postback click event of Button on the page,I am trying to get the value of the TextBox's Text Property.
I am able to get the value in the click event of the Button when the control is dynamically added in the Page_Load event and not the OnPreInt method.
I think that the Text value is retained in the ViewState even though the control is been added in Page_Load method.
following the code:
<div>
<p>
<asp:Label ID="lbl" runat="server" />
</p>
<p>
<asp:PlaceHolder ID="plcHolder" runat="server"></asp:PlaceHolder>
</p>
<p>
<asp:Button ID="btn" runat="server" Text="Click" OnClick="btn_Click" />
</p>
</div>
private void _createTextBox()
{
TextBox textBox = new TextBox();
textBox.ID = "txtBox";
textBox.Width = 250;
textBox.ReadOnly = false;
plcHolder.Controls.Add(textBox);
}
protected void Page_Load(object sender, EventArgs e)
{
_createTextBox();
if (!this.IsPostBack)
{
Control ctrl = plcHolder.FindControl("txtBox");
if (ctrl != null)
{
TextBox txtBox = ctrl as TextBox;
txtBox.Text = DateTime.Now.ToString();
}
}
}
protected void btn_Click(object sender, EventArgs e)
{
Control ctrl = plcHolder.FindControl("txtBox");
if (ctrl != null)
{
TextBox txtBox = ctrl as TextBox;
lbl.Text = txtBox.Text;
}
}
Kindly let me know is this correct or what am i doing wrong?
There's tons of info on the web about the ASP.NET life cycle, but i can't seem to figure out when to dynamically add controls to the page.
In general there are two situations; an aspx page with a masterpage, and one without. The book i'm currently reading (70-515 self prep) says to add controls to a page without a master page in the preinit eventhandler. To dynamically add controls to a contentpage, i should place that logic in the init eventhandler.
According to MSDN (http://msdn.microsoft.com/en-us/library/ms178472.aspx) I should create or recreate dynamic controls in the preinit eventhandler, and only read or initialize properties of controls in the init eventhandler (which makes most sense to me). Googling around I see lots of people using the init eventhandler to add controls.
So, i'm a little bit lost here - what is the correct way? And when using the preinit eventhandler, how could you add controls to your page when all controls are null? For instance, when you need to add a dynamically created textbox to a panel control?
Kind regards,
Unless you need to play around with setting control properties prior to tracking ViewState, I would personally go ahead and place my dynamic control addition logic in the OnInit event.
If you really want to dynamically add a control during the PreInit (when using master page) you can always do something like this:
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
TextBox textBox = new TextBox();
textBox.Text = "Dynamic TextBox";
textBox.Width = 100;
textBox.ReadOnly = false;
var master = this.Master;
plcHolder.Controls.Add(textBox);
textBox.ApplyStyleSheetSkin(this.Page);
}
accessing the "Master" property would instantiate the controls
and it should work, but you get nested master pages scenarios (this.Master.Master ...), update panels and so on.
This might be relevant and helpful: http://weblogs.asp.net/ysolodkyy/archive/2007/10/09/master-page-and-preinit.aspx
Moreover, one reason I can think of (besides following the defined page lifecycle) MS recommends that we place all the logic for dynamic control creation in the Preinit event so we can take advantage of the theme service, which will apply all available skin properties automatically for us, before the Init event takes place.
Say your markup looks something like that:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Trace="true" Inherits="_Default" Theme="Test" %>
...
<form id="form1" runat="server">
<div>
<p>
<asp:TextBox ID="TextBox1" runat="server" TextMode="Password" Text="Control TextBox"></asp:TextBox>
</p>
<p>
<asp:PlaceHolder ID="plcHolder" runat="server"></asp:PlaceHolder>
</p>
</div>
</form>...
and you have a skin like this:
<asp:TextBox runat="server" BackColor="Yellow" Wrap="false" Text="Skin property!" > </asp:TextBox>
Just add this to your code behind:
private TextBox tb1;
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
tb1 = new TextBox();
tb1.Text = "PreInit Dynamic TextBox";
Trace.Write(String.Format("tb1 Wrap Property-> {0}",tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
Trace.Write("Add tb1 to the placeholder.");
plcHolder.Controls.Add(tb1);
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
}
protected override void OnInit(EventArgs e)
{
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
base.OnInit(e);
}
protected void Page_Load(object sender, EventArgs e)
{
Trace.Write(String.Format("tb1 Wrap Property-> {0}", tb1.Wrap));
Trace.Write(String.Format("tb1 Text Property-> {0}", tb1.Text));
}
You will notice how before going into the Init event all skin properties are already applied to the dynamically created textbox :)
The PreInit event was new to me, but I guess it makes sense, so that you have an intermediary step in between the loading of controls and viewstate load to do additional work. We've used init event to load dynamic controls and this has always worked for us with no issues. I think you'll be OK with either, but if MS recommends PreInit, I'd say go that route. THis way, in Init, you can do any additional work you may need and separate out the routine that creates the UI vs. the routine that may update it before viewstate load.
HTH.
Currently struggling with a problem that I've encountered variations on in the past. At the moment a worthwhile solution escapes me, but it seems such an obvious issue that I can't help wondering whether or not there's a "best practice" approach I should adopt.
Without code, here's the issues in a nutshell:
page has databound control (a repeater) which isn't populated until user inputs data and clicks a button.
Repeater item template contains a button
User clicks button, page posts back. On load, the repeater is actually empty so event is never handled because the originating control no longer exists
Go back to the beginning of wretched cycle
I've confirmed that this is the problem because if you provide the repeater with some static data on page load, everything works fine. But of course that's no use because it has to be populated dynamically.
Is there a commonly approved way round this headache? I can store the data in session and re-use it on page load, but it seems terribly clumsy.
Cheers,
Matt
If the event is being fired by a button within a repeater then this would bubble up to the repeaters ItemCommand event. Using a buttons CommandName and CommandArgument parameters you can then identify which button was clicked and act accordingly. Below is some basic markup and code behind to demonstrate the approach:
HTML:
<asp:Repeater ID="rptTest" runat="server" onitemcommand="rptTest_ItemCommand"
onitemdatabound="rptTest_ItemDataBound">
<ItemTemplate>
<p>
<asp:Button ID="btnTest" runat="server" />
</p>
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="btnLoad" runat="server" Text="Load" onclick="btnLoad_Click" />
Code behind events:
protected void rptTest_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Button button = (Button)e.Item.FindControl("btnTest");
button.Text = string.Format("Button {0}", e.Item.DataItem.ToString());
button.CommandName = e.Item.ItemIndex.ToString();
}
protected void rptTest_ItemCommand(object source, RepeaterCommandEventArgs e)
{
Response.Write(string.Format("Postback from button {0}", e.CommandName));
}
protected void btnLoad_Click(object sender, EventArgs e)
{
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
rptTest.DataSource = list;
rptTest.DataBind();
}
Hopefully i've understood the problem and this helps.
If any of your controls are created dynamically, then they have to be recreated during post back in order for the events etc to get hooked back up.
If this is the case, take a look at a control built by a guy named Denis Bauer. We use this with just some slight modifications and it's perfect.
I´ve read most posts here but i can´t figure out why the "CheckedChanged" Event is not firing. Here is my situation.
I´m using a Repeater to generate Items out of a Database. Each ReapeaterItem should include an UpdatePanel, because i have to Update the Controls inside the UpdatePanel and do not want to reload the complete page. Inside these dynamically generated UpdatePanels (each RepeaterItem has one) i´m adding up to three Checkboxes dynamically (based on the Database). These Checkboxes need to fire the "CheckedChanged" event, because on some conditions i want to enable/disable/check/uncheck Checkbox1, 2 or 3 based on business logic. ... Hope you got this so far. I´m adding all Controls and have the EventHandler Added. But the generated Code does not reflect the Event Handler. I tried OnItemDataBound, OnItemCreated, PreRender, ... Events to add the Eventhandler too, but i was not able to find the CheckBox-Control with the ID.
I´m totally lost with this and on the way to use Buttons instead of Checkboxes. From what i read so far is that with Buttons i can use the CommandName from the Button and the ItemCommand-Event from the Repeater to get a workaround, but then i need to reflect the "Check" on the Page in some way.
btw, every Repeater (8) sits inside an ajaxtoolkit-accordion control.
Here i give you some Code:
aspx-Page
<asp:Repeater ID="RepeaterAccordionPane2" runat="server">
<ItemTemplate>
HTML Stuff<%# DataBinder.Eval(Container.DataItem, "Header")%>HTML Stuff<%# DataBinder.Eval(Container.DataItem, "Beschreibung")%></td>
<asp:UpdatePanel ID="UpdatePanel2" runat="server" UpdateMode=Conditional>
<ContentTemplate>
</ContentTemplate>
</asp:UpdatePanel>
HTML Stuff
</ItemTemplate>
</asp:Repeater>
Here is the Page_Load Part
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dvAlleArtikel = new System.Data.DataView(...Database...);
[... some other code here ...]
RepeaterAccordionPane2.DataSource = dvAlleArtikel;
//RepeaterAccordionPane2.ItemCreated +=new RepeaterItemEventHandler(RepeaterAccordionPane2_ItemCreated);
//RepeaterAccordionPane2.PreRender +=new EventHandler(RepeaterAccordionPane2_PreRender);
RepeaterAccordionPane2.DataBind();
int nUpdatePanelIndex = 0;
foreach (Control crInRepeater in RepeaterAccordionPane2.Controls)
{
if (crInRepeater.GetType() == typeof(RepeaterItem))
{
foreach (Control crInRepeaterItem in crInRepeater.Controls)
{
if (crInRepeaterItem.GetType() == typeof(UpdatePanel))
{
LiteralControl litTabelleBeginn = new LiteralControl("<table width=\"100%\" border=\"0\" cellspacing=\"0\" cellpadding=\"2\">");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litTabelleBeginn);
if (dvAlleArtikel[nUpdatePanelIndex]["ArtNr1"].ToString() != "0")
{
CheckBox CheckBox1 = new CheckBox();
CheckBox1.ID = dvAlleArtikel[nUpdatePanelIndex]["ArtNr1"].ToString();
CheckBox1.Text = (dvAlleArtikel[nUpdatePanelIndex]["CheckBoxLbl1"].ToString() == "" ? "leer" : dvAlleArtikel[nUpdatePanelIndex]["CheckBoxLbl1"].ToString());
CheckBox1.AutoPostBack = true;
CheckBox1.CheckedChanged +=new EventHandler(CheckBox1_CheckedChanged);
LiteralControl litNeueTabellenZeileBeginn = new LiteralControl("<tr><td width=10><img src=\"images/helper/spacer.gif\" width=\"10\"></td><td height=\"20\">");
LiteralControl litNeueTabellenZeileEnde = new LiteralControl("</td><td width=\"100\" height=\"20\">" + dvAlleArtikel[nUpdatePanelIndex]["ArtPrice1"].ToString() + " € </td></tr>");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litNeueTabellenZeileBeginn);
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(CheckBox1);
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litNeueTabellenZeileEnde);
}
[... some other code here...]
LiteralControl litTabelleEnde = new LiteralControl("</table>");
((UpdatePanel)crInRepeaterItem).ContentTemplateContainer.Controls.Add(litTabelleEnde);
nUpdatePanelIndex++;
}
}
}
}
This code is never reached:
protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
{
int foo = 0;
}
This is the CheckBox-Code generated:
<input id="AccordionPane2_content_RepeaterAccordionPane2_ctl00_6200" type="checkbox" name="AccordionPane2_content$RepeaterAccordionPane2$ctl00$6200" onclick="javascript:setTimeout('__doPostBack(\'AccordionPane2_content$RepeaterAccordionPane2$ctl00$6200\',\'\')', 0)" />
The Event is generated, but when i click the Checkbox all Content in the UpdatePanel is gone and the CheckedChanged-EventHandler is not fired.
What am i doing wrong?
Thanks to all advice, i´m really stuck.
mk
The first time the page loads you are adding all the checkboxes to the Controls collection, and they get rendered. When you do a postback (through the CheckBox's AutoPostBack) you have a check if(!IsPostBack) that doesn't allow the checkboxes to be added to the Controls collection on the postback. Because of that, you won't see the controls and the page, and when the page lifecycle tries to call the events (which occurs AFTER Page_Load), the controls that created the events are no longer there.
You will need to refactor your Page_Load method so it does two things - 1, regardless of the value of IsPostBack bind the repeaters and create the dynamic controls. 2, if IsPostBack==false, i.e., an initial load, then set the values of the dynamic controls. you don't want to set the values of the dynamic controls when IsPostBack==true because then you will lose the values the user entered.
also, just a note:
if (crInRepeater.GetType() == typeof(RepeaterItem))
can be rewritten as:
if (crInRepeater is RepeaterItem)