In my ASP.NET app I have Update Panel and Custom server control in it.
This Custom control has inside Literal Control. I try to set it's text property programmatically. But it doesn't render, because Literal Control is in Update Panel.
How can I solve this? Thanks very much.
Here is my code:
<asp:UpdatePanel runat="server" ID="updPanel">
<ContentTemplate>
<st:AspGridViewTitlePanel runat="server" ID="GridTitle" Width="100%">
</st:AspGridViewTitlePanel>
</ContentTemplate>
</asp:UpdatePanel>
AspGridViewTitlePanel - it's my server control. It has such code:
this.myLiteralControl = new LiteralControl();
this.myLiteralControl.Text = "Some text";
protected void page_load(object sender, args e) {
if (!Page.IsPostBack) {
LiteralControl myLiteralControl = new LiteralControl();
myLiteralControl.Text = #"<span> MY TEXT </span>";
UP1.ContentTemplate.Controls.Add(myLiteralControl);
}
}
Adding controls dynamically to an UpdatePanel in ASP.NET AJAX
Related
I've got a sitecore proejct, in which I have prepared a sub-layout in the form of an ascx User Control. I need to set up cascading drop downs in this user control, and based on what I found an UpdatePanel is the way to go. The problem is that the UpdatePanel seems to be refreshing the whole control, which I don't think is the correct behaviour.
I understand there are some similar questions on SO, but none of the solutions worked for me. I'm also beginning to suspect that this may be a Sitecore specific issue.
Here is a code sample of the user control:
<p><%= MyItem.Text %>" /></p>
<asp:UpdatePanel ID="LocationFilterUpdatePanel" runat="server">
<ContentTemplate>
<asp:DropDownList ID="DDL1" OnSelectedIndexChanged="DDL1_SelectedIndexChanged" runat="server" AutoPostBack="true">
</asp:DropDownList>
<asp:DropDownList ID="DDL2" OnSelectedIndexChanged="DDL2_SelectedIndexChanged" runat="server" AutoPostBack="true">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
And the Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
{
var context = new SitecoreContext();
//Get Model from Sitecore
DDL1.DataSource = Model.Data;
DDL1.DataValueField = "Id";
DDL1.DataTextField = "Name";
DDL1.DataBind();
}
}
protected void DDL1_SelectedIndexChanged(object sender, EventArgs e)
{
var context = new SitecoreContext();
//Get Model from Sitecore
DDL2.DataSource = Model.Data;
DDL2.DataValueField = "Id";
DDL2.DataTextField = "Name";
DDL2.DataBind();
}
protected void DDL2_SelectedIndexChanged(object sender, EventArgs e)
{
}
The page loads fine, but (when debugging) changing the DDL1's index it will show a Null exception in MyItem.Text. This is outside the control panel. Note: I have also added a script manager.
There are plenty of things I've tried. Setting different update modes, updated the AjaxToolkit in my solution by executing Install-Package AjaxControlToolkit from the Package Manager Console... but the behaviour remains the same.
Thank you.
Put the databinding for DDL1 to the OnInit, rather than the Page_Load.
And don't include the if statement in there, just do the databind.
After the OnInit the selected values will be correctly set and you will be able to access the DDL1's options in the other event handlers.
You have asp:DropDownList control with an AutoPostBack set to true.
Remove the AutoPostBack=true from the Dropdownlist control and set an Async trigger for your UpdatePanel, set to the Dropdownlist and its eventname="SelectedIndexChanged"
This is a know issue, and you find a lot of documentation about it.
I have a repeater which includes a radio button in each item, and the whole thing sites inside an update panel. When I select a radio button the whole page reloads. Why is it not just updating the update panel. I've reduced this to a pretty simple example to avoid clutter. Code here...
ASPX...
<asp:ScriptManager ID="SM1" runat="server" />
<asp:UpdatePanel ID="up1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater runat="server" ID="history">
<ItemTemplate>
<asp:RadioButton runat="server" ID="radioButton" AutoPostBack="true" GroupName="HistoryGroup" OnCheckedChanged="RadioButton_CheckChanged" /><br />
</ItemTemplate>
</asp:Repeater>
<p><asp:Literal runat="server" ID="output" /></p>
</ContentTemplate>
</asp:UpdatePanel>
Code...
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<int> list = new List<int>();
for (int i = 0; i < 20; i++)
list.Add(i);
history.DataSource = list.ToArray();
history.DataBind();
}
}
protected void RadioButton_CheckChanged(Object sender, EventArgs e)
{
output.Text = DateTime.Now.ToString();
}
}
Setting ClientIDMode=Auto on the RadioButton should fix it (it's an infamous .NET bug, http://connect.microsoft.com/VisualStudio/feedback/details/584991/clientidmode-static-in-updatepanel-fails-to-do-async-postback)
please add up1.Update() after output.Text = DateTime.Now.ToString(). Your RadioButton is not the trigger for updatepanel
Turns out the solution was to remove the GroupName from the RadioButton. When I remove this tag it fires asynchronously and just updates the panel. I don't actually need this tag anyway (due to the known bug where GroupName doesn't work on RadioButtons in Repeaters) as I handle the grouping within my click event (i.e. uncheck any other RadioButtons of the same name in other repeater items).
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.
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.
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.