I have a page with an UpdatePanel that contains a Repeater and a text box with the number of items in the repeater. When I change the value, the page is supposed to post back and redraw the Repeater with the updated number of items. This works in principle, but the page ends up frozen after post-backs and does not accept any input - in IE 8 only. It works perfectly fine in Firefox. For instance, the context menu does not appear when I right-click in controls, and I cannot enter text in text boxes.
When I take out the UpdatePanel, the page works fine, but of course refreshes on every post-back event. This is not necessarily related to the Repeater on the page. I think I am seeing this on other pages. What's the trick here?
<asp:UpdatePanel ID="uPanel" runat="server" UpdateMode="Conditional"
EnableViewState="true" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Panel ID="Panel1" runat="server" DefaultButton="btnSubmit">
<asp:TextBox ID="tbItems" runat="server" AutoPostback="true"
OnTextChanged="textchanged_Items"/>
<asp:Repeater id="rptItems" runat="server"
OnItemDataBound="repeaterItem_Databound">
<...>
</asp:Repeater>
protected void textchanged_Items(object sender, EventArgs e) {
try {
// this methods rebinds the repeater to a List after changing
// the number of items in the list
ReflowItemRepeater();
// This is not really necessary, since Databind() appears to
// cause an update. I tried it anyways.
uPanel.Update();
}
catch (Exception ex) {
ShowError(this, "Error displaying the item list.", ex, true);
}
}
I ended up removing the update panel.
One month later, different page, I am still and again fighting this. The situation is the same.
An update panel, a repeater (actually 2 nested repeaters), and a control in the repeater that fires a postback event. The server processes the event correctly and returns control, but the browser (IE8) never refreshes the update panel. The page is unresponsive, as if in some sort of dead-lock situation. I can unlock it by clicking on a button that fires another postback event (also in the update panel). But the text boxes in the panel are not clickable or editable when this happens.
Also, it happens only the first time. Once I have "freed up" the lock, or whatever it is, it will not happen again on this page, even when I repeat the exact same steps that led to it.
When this happens, the JIT debugger does not report anything.
I would actually set Triggers within your updatepanel.
I'm not sure you need to call .Update in your code behind as the updatepanel will be updated when the trigger occurs.
Try this:
My gut feeling is that it has something to do with the use of the OnTextChanged event. For kicks, try adding a button next to the text box, and reflow the repeater when the button is clicked instead. Does IE still freeze?
So I stripped this page down to the minimum and I found out what is doing it - the AjaxToolkit:CalendarExtender. If I take it out, everything works fine. Still, I would be curious to know if there is a workaround.
Here is a link to my test page. I will keep it up for a few days.
To see the issue, select "2" from the drop-down, then type something into the first quantity field and tab out. The cursor will blink in the next field, but it does not allow input. This happened in IE8, not in Firefox.
Edit: Actually, when I went back to the full page and removed the CalendarExtender, it was still not working. I do suspect that this issue has to do with controls posting back in the UpdatePanel, but I just can't pin it down. It seems seems to be one of these things where a combination of x things does not work, while any combination of (x-1) things does work.
Regarding the initial question, here's a working sample. I don't know if it's anyhow helpful, but just to make sure...
<%# Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server"><title>Ajax Test</title></head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server" />
<asp:UpdatePanel runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Label runat="server" AssociatedControlID="txtTest">
Enter 'fruit' or 'vegetables':
</asp:Label>
<asp:TextBox
runat="server" ID="txtTest" AutoPostBack="true"
OnTextChanged="Handler_Test_TextChanged"
/>
<asp:Repeater runat="server" ID="rptItems">
<HeaderTemplate><ul></HeaderTemplate>
<ItemTemplate><li><%# Container.DataItem.ToString() %></li></ItemTemplate>
<FooterTemplate></ul></FooterTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
<script runat="server">
static readonly string[] Fruit = new string[]
{ "Apples", "Oranges", "Bananas", "Pears" };
static readonly string[] Veg = new string[]
{ "Potatoes", "Carrots", "Tomatoes", "Onion" };
void Handler_Test_TextChanged(object s, EventArgs e)
{
if(txtTest.Text == "fruit") rptItems.DataSource = Fruit;
else if(txtTest.Text == "vegetables") rptItems.DataSource = Veg;
else return;
rptItems.DataBind();
}
</script>
Related
I know even if the ViewState is disabled for the TextBox, we are not losing the data because it implements the IPostBackDataHandler interface.
<asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"/>
But my question is why this happens for label too? Why label is not losing it's data even if the ViewState is disabled since the label doesn't implements the IPostBackDataHandler interface?
<asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled"/>
TextBox definition:
public class TextBox : WebControl, IPostBackDataHandler,
Label definition:
public class Label : WebControl, ITextControl
My code:
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled" Text="Before click"></asp:Label>
<asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_OnClick"/>
</div>
</form>
And code behind:
protected void Button1_OnClick(object sender, EventArgs e)
{
Label1.Text = "Changed.";
}
I expected to see the "Before click" in my label after I clicked the button but I see the "Changed" text in my label after I clicked the button.
Ok I deleted my previous answer, I will try to re-state it with an example.
First, as others stated, the idea of ViewState is to hold the state between postbacks, rather than during a single page load cycle, so what you're seeing is the expected behavior.
To see the difference with an example, try adding your label with 2 buttons:
<asp:Label ID="Label1" runat="server" EnableViewState="False" Text="Before click"></asp:Label>
<asp:Button ID="btn1" Text="Click" OnClick="btn1_Click" runat="server" />
<asp:Button ID="btnReset" Text="Reset" OnClick="btnReset_Click" runat="server" />
Where btn1 sets the value to "Changed", and btnReset has an empty handler.
Now with EnableViewState set to False, if you click on btn1 the page reloads, btn1_Click is executed, and the page is rendered with the label value = "Changed", if you click btnReset the page will reload again, but since view state is disabled, the label will revert to its original text "Before click"
If you set EnableViewState to True on the lable and click btn1 then btnReset, the label value will stay as "Changed", since the state is kept during postbacks
Hope that clarifies things a bit
This is going to be long and detailed.
Let's start with this markup. Almost identical to yours, with one additional button and a label. I'll explain why we need them later.
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled" Text="Before click"></asp:Label>
<asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_OnClick"/>
<asp:Label ID="Label2" runat="server" Text="Blah" />
<asp:Button ID="Button2" runat="server" Text="Button" OnClick="Button2_OnClick"/>
</div>
</form>
And we'll use this code behind. Again, I'll explain the purpose of the second handler later on:
protected void Button1_OnClick(object sender, EventArgs e)
{
Label1.Text = "Changed";
}
protected void Button2_OnClick(object sender, EventArgs e)
{
Label2.Text = Label1.Text;
}
Let's see what happens when we initially load the page. First ASP.NET reads all the markup, and then goes through the page life cycle with all the events. In markup parsing stage Label1 gets assigned text Before click, and it is never changed later during initial load. So later during rendering phase this is what is getting rendered into HTML and sent to browser. Thus Before click is displayed on the screen. Nice and easy.
Now we click Button1. Postback occurs, which is a term that describes a request sent to the same page by one of its controls after it was initially loaded. Again, everything starts with ASP.NET parsing the markup, and again Label1 gets assigned text Before click. But then page life cycle events happen, including control event handlers. And in the handler for Button1 the text of Label1 is changed to Changed. Now here is the important thing to note: if ViewState for the Label1 was enabled, this new value would be stored in there, and so called tracking would be enabled for property Label1.Text. But ViewState is disabled, and so the new value is not stored anywhere except Label1. Next comes the rendering page stage, and since Label1.Text still holds the value Changed this is what is rendered into HTML and sent to the browser to display. Note however that this new value is not sent inside the ViewState field. As you can see, whether ViewState is enabled or not plays no role in what is displayed after this postback.
Now we'll click Button2, which would trigger another postback. Again, ASP.NET parses the markup, again Label1 gets text Before click. Then comes ViewState loading part. If ViewState for Label1.Text was enabled, it would load changed value into this property. But ViewState is disabled, and so the value stays the same. Thus, when we reach Button2 click handler, the value of Label1.Text is still Before click, which is assigned to Label2.Text. But Label2 has ViewState enabled, and so this new value for its text is stored in ViewState and sent to the client (ViewState is implemented as a hidden field on the client side). When everything gets to the browser, we can see Label1 and Label2 both displaying Before click.
And to nail it down we'll do a third postback, now clicking Button1 again. Just as during the first postback, Label1 ends up with Changed text. But what about Label2? Well, this one has ViewState enabled, so during initial markup parsing ASP.NET assigns it the value Blah, and during ViewState loading it replaces this value with Before click. Nothing else affects this value during the page life cycle (we did not click Button2 this time), and so we end up seeing Changed and Before click in the browser.
Hopefully it makes it clear what the ViewState is for and what disabling it does. If you want to dive even deeper into how ViewState works, I would greatly recommend this article: TRULY Understanding ViewState.
I think you have wrong understanding what ViewState is.
Data in ViewState is being stored BETWEEN requests, but not DURING page lifecycle.
BTW - ViewState data is generated after PreRenderComplete event in SaveStateComplete event.
https://msdn.microsoft.com/en-us/library/ms178472.aspx
If you have ViewState switched off - just think that it will not be generated in output.
During page lifecycle all data assigned to controls(and also to page fields and properties, as the page is just a class) will be rendered as you defined in aspx. But will be lost after, unless is saved in ViewState.
I got a situation here.
I have around 5 ASP controls in my page including some Text-Box and Radio Buttons. These controls are the part of a form where the user will fill data one by one into these controls. Now, the problem is each of these controls have AutoPostBack = True and OnTextChanged or OnCheckedChanged event associated with it.
Here comes the problem. Whenever the user fills one of these controls and try to navigate to the next control, that control needs Double-Click to get focus. It is very inconvenient to double click every control while filling up the form.
I tried to come over the situation by setting Page.SetFocus(<control>); in every OnTextChanged event to the next control in the form. But the same doesn't work in case of a Radio Button. It also doesn't work when the sequence of focus is changed.
I need a work-around to overcome the problem. I can't remove the OnTextChanged or OnCheckedChanged events due to the requirements.
What's actually happening is the page is being posted back and then focus is shifting back to the control that caused the postback. A double click isn't actually strictly happening. The first click causes the first control to lose focus, thus causing the postback. The second click then focuses the control you want after the postback has occurred.
What you can do is capture the control that has received focus prior to the postback and when the page reloads set focus back to that control.
Here's an example (Updated):
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" OnTextChanged="TextBox1_TextChanged" AutoPostBack="True"
onFocus="SetNextControl(this);"></asp:TextBox>
<asp:RadioButton ID="RadioButton1" runat="server" OnCheckedChanged="RadioButton1_CheckedChanged"
AutoPostBack="True" GroupName="RBGroup" onClick="SetNextControl(this);" />
<asp:RadioButton ID="RadioButton2" AutoPostBack="True" GroupName="RBGroup" runat="server" onClick="SetNextControl(this);"/>
<asp:TextBox ID="TextBox2" runat="server" OnTextChanged="TextBox2_TextChanged" AutoPostBack="True"
onFocus="SetNextControl(this);"></asp:TextBox>
</div>
<asp:HiddenField ID="HiddenField1" runat="server" />
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {
if (document.getElementById("<%=HiddenField1.ClientID %>").value != "") {
var controlToFocus = document.getElementById(document.getElementById("<%=HiddenField1.ClientID %>").value);
controlToFocus.focus();
document.getElementById("<%=HiddenField1.ClientID %>").value = "";
}
})
function SetNextControl(e) {
document.getElementById("<%=HiddenField1.ClientID %>").value = e.id;
}
</script>
</asp:Content>
The above sample isn't perfect, I'm not sure if it'll work the way you want with RadioButtons as there is no onFocus event for them. I've changed them to use onClick so that at least focus remains on the last selected radio button. Hopefully this at least get's you a little bit closer to what you want.
I want to do page load every 5 sec so I have this in my head content
<meta http-equiv="refresh" content="5" />
Because of this the whole page refreshes. I just want to refresh the gridview and the graph that I have in the page. How can I do that without refreshing the whole page.
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" EnablePageMethods="true" EnablePartialRendering="True"
runat="server">
</asp:ToolkitScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<div id="pie">
<canvas width="125" height="450" id="progress1">[No canvas support]</canvas>
<canvas id="pie1" position="relative" width="400" height="400">[No canvas support]</canvas>
</div>
<asp:Panel runat="server" ID="Panel_Users">
<asp:GridView ID="Grid_UserTable" runat="server"
OnRowDataBound="MyGrid_RowDataBound">
<Columns> </Columns>
</asp:GridView>
</asp:Panel>
<asp:Timer ID="TimerClickEvent" runat="server" Interval="4000" ontick="TimerClickEvent_Tick"></asp:Timer>
</ContentTemplate>
</asp:UpdatePanel>
protected DateTime LastUpdate
{
get
{
return (DateTime)(ViewState["LastUpdate"] ?? DateTime.Now);
}
set
{
ViewState["LastUpdate"] = value;
}
}
protected void TimerClickEvent_Tick(object sender, EventArgs e)
{
if (LastUpdate.AddSeconds(5.0) < DateTime.Now)
{
UpdatePanel1.Update();
LastUpdate = DateTime.Now;
}
}
protected void Page_Load(object sender, EventArgs e)
{
ToolkitScriptManager1.RegisterAsyncPostBackControl(TimerClickEvent);
if (!IsPostBack)
{
LastUpdate = DateTime.Now;
}}
Doesn't reload. where am I going wrong
Place the panel inside an UpdatePanel and use method updatePanelID.Update() to update the update the Panel containing GridView. See this for more details
Instead of button click event you can use a timer for that.
If you only want to refresh a region, there are 2 options:
load that into an <iframe> and let it do whatever it wants (via meta-refresh on the document inside the <iframe>
reload the implacted region via javascript, perhaps jQuery's .load() method, i.e. $('#id').load(url);
A meta-refresh on the entire page will, by necessity, reload the entire page.
For a built in asp.net solution, use an <asp:UpdatePanel> along with an <asp:Timer> control.
Set the update panel to update based on the Timers Tick event. This will then only update the content within the update panel.
HOWEVER, this is a quick and dirty solution (in my opinion) because even though the content on the page only updates within the update panel, the whole page is actually posted back each time, and anything within the Page_Load method will be processed again.
Another solution would be to use some javascript ajax, and only update what you need to update. A great javascript library which will help you with this is jQuery, and then use the AJAX features of this. This will allow you to reload on the areas that you need, and give you far greater control over what is happening.
I would forget about the AJAX Control Toolkit, and look more into jQuery Ajax and jQuery UI.
I have the following ASPX code:
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel runat="server" ID="UpdatePanel" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button runat="server" ID="UpdateButton1" OnClick="NextImg_Click" Text="Update" />
<asp:Repeater runat="server" ID="urlsUpdateRepeater">
<ItemTemplate>
<!-- THIS WOULD BE A LOOP FROM HERE -->
<!-- OPENS RESULT ITEM DIV CONTAINER -->
<div id="result_item">
<a href="<%# Eval("myUrl") %>" target="_blank">
<%# Eval("urlPageTitle")%></a>
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
I have a NextImg_Click() event which works fine.
I use this code for DataBind... what is the Update method?
urlsUpdateRepeater.DataSource = resultsCollection;
urlsUpdateRepeater.DataBind();
Everything would appear to be in order. But every time the Update button is clicked it re-renders the whole page instead of the partial-postback UpdatePanel only.
It is driving me completely mad as I can't see anything wrong with the code. Is there some simple thing I'm missing?! Please help!
The search and data is displayed correctly (inside the panel) it just will not do a partial postback.
Appreciate your help with my noob problems!
Because the button is inside your UpdatePanel's ContentTemplate, it is unnecessary to take any extra action to get a partial page postback.
Try removing the line from your Page_Load() method.
Taken from MSDN:
Use the RegisterAsyncPostBackControl
method to register controls outside an
UpdatePanel control as triggers for
asynchronous postbacks, and to
potentially update the content of an
update panel. To update an UpdatePanel
control programmatically, call the
Update method.
So, you're control (UpdateButton1) is inside the UpdatePanel, no need for the ScriptManager1.RegisterAsyncPostBackControl call - ditch it and your problem is solved.
The problem was that my <form> tag was nested further into the document than it's corresponding end tag (with Warning!)...
Upon moving my form tag - it worked!
Entirely my fault, thanks guys.
I have two placeholders in one page and basically my requirement is that I want to show other placeholder on click of button which is in first placeholder without refreshing the page.
But when I m clicking on the button in 1st placeholder it is refreshing the page and then showing me second placeholder.I m open to hear any other suggestions also if it is not possible through placeholder.
Can anyone tell me how to achieve this?
Thanks,
You could, as suggested, use an UpdatePanel. As long as you ensure that both PlaceHolders exist within the ContentTemplate element, you will be able to switch between the PlaceHolders without the whole page being refreshed.
However, such convenience comes at the cost of control. This isn't a knock on Microsoft. The same problems exist for most ready-rolled solutions.
Whatever route you choose, you're going to need something to refresh part of the current page's DOM. And really, this means Javascript.
Do the actions in PlaceHolder 1 change the content of PlaceHolder 2? If not, you could render both, and simply use CSS to make PlaceHolder 2 invisible on load. You could then use Javascript events to make it visible as desired.
If actions on PlaceHolder 1 do affect PlaceHolder 2, then the above solution won't work, as you'll need to work out what PlaceHolder 2 is going to contain before displaying it.
The real question is whether you employ your own Javascript ( possibly in conjunction with a mature js library like mootools or jQuery ), and maybe learn something in the process, or run with the ASP .NET AJAX stuff for the quick solution, and hope you don't run into any problems.
You could wrap an updatepanel around you PlaceHolder:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:PlaceHolder runat="server" ID="placeholder">hello</asp:PlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
placeholder.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
placeholder.Visible = true;
}
This wil generate a partial postback (via AJAX), so only the content inside my updatepanel gets updated. In the <Triggers>-section, I specify that my Button will trigger the postback.
Either use an UpdatePanel control (part of the MS ajax framework) or use JavaScript. Placeholder would have to render an HTML element, and I'm not sure that it does. If it doesn't, you can use a panel instead, and then in JS do:
function show() {
var panel = document.getElementById("<%= panel2.ClientID %>");
panel.style.display = "true";
}
<asp:Button id="btn1" runat="server" OnClientClick="show();return false;" />
HTH.