Showing posts with label events. Show all posts
Showing posts with label events. Show all posts

Wednesday, March 28, 2012

Control focus on autopostback in UpdatePanel

I have an Update Panel with a bunch of textboxes, and have code for the _onTextChanged events of some of them, so I have enabled AutoPostBack=true.
This is a data entry screen, so the TabIndex is critical. In Mozilla, when the textbox posts back, the TabIndex moves to the next box as expected. In IE, the reload of the page seems to reset the TabIndex to the first textbox.

Any ideas on how I can make my code behave in IE like it does in Mozilla?

ThanksActually, I asked same question yesterday. Unfortunately, no answers yet.
You could use Control.Focus(), to manually set the focus to the next control (either in the server code or with javascript).
That's the strange thing about it... I already had that, and I watch it work in stepping through the _onTextChanged of the control, but then the focus just gets changed/set to nothing after my code set it properly...

Control Events in Accordion

I have an accordion control which contains several panes each containing a GridView (by using ConentTemplate). I would like to give the user the ability to edit GridView items inline. The problem is that I must click twice to put the item into edit mode. I have seen other posts with similar problems but no definite solution. Any help would be greatly appreciated.

1 <ajaxToolkit:Accordion ID="Accordion1" runat="server" HeaderCssClass="accordionHeader"2 ContentCssClass="accordionContent" SelectedIndex="0"3 AutoSize="None" FadeTransitions="false" FramesPerSecond="40" TransitionDuration="250" EnableViewState="true" >4567 <HeaderTemplate><a class="accordionLink" id="accordionLink" href="http://links.10026.com/?link=" onclick="return false;"><%# ((Person)((DictionaryEntry)Container.DataItem).Key).FirstName + " " + ((Person)((DictionaryEntry)Container.DataItem).Key).LastName%></a></HeaderTemplate>89 <ContentTemplate>10111213 <asp:GridView EnableViewState="true" ID="GridViewOpen" OnRowUpdating="GridViewOpen_RowUpdating" OnInit="GridViewOpen_Init" OnRowEditing="GridViewOpen_RowEditing" OnRowCancelingEdit="GridViewOpen_RowCancelingEdit" OnSelectedIndexChanged="GridViewOpen_SelectedIndexChanged" runat="server" DataSource="<%# ((DictionaryEntry)Container.DataItem).Value%> "14 AutoGenerateColumns="false" AutoGenerateEditButton="true" AutoGenerateSelectButton="false" AllowSorting="true">15 <Columns>16171819 <asp:TemplateField HeaderText="MoNumber" SortExpression="MoNumber">20 <EditItemTemplate>21 <asp:TextBox ID="LabelEditMoNumber" runat="server" Text='<%# Bind("MoNumber")%>'></asp:TextBox>22 </EditItemTemplate>23 <ItemTemplate>24 <asp:Label ID="LabelViewMoNumber" runat="server" Text='<%# Bind("MoNumber")%>'></asp:Label>2526 </ItemTemplate>27 </asp:TemplateField>2829303132 <asp:TemplateField HeaderText="Location" SortExpression="LocationId">33 <EditItemTemplate>34 <asp:DropDownList runat="server" id="dataLocationId" DataSourceID="objDsLocationId" DataTextField="Name" DataValueField="LocationId" SelectedValue='<%# Bind("LocationId")%>'></asp:DropDownList>35 </EditItemTemplate>36 <ItemTemplate>37 <asp:Label ID="Label2" runat="server" Text='<%# FindLocation(Eval("LocationId"))%>'></asp:Label>38 </ItemTemplate>39 </asp:TemplateField>40 <asp:TemplateField HeaderText="Time (Hrs)">41 <ItemTemplate>42 <asp:Label ID="Label3" runat="server" Text='-'></asp:Label>43 </ItemTemplate>44 </asp:TemplateField>4546474849 </Columns>50 </asp:GridView>5152 </ContentTemplate>5354 </ajaxToolkit:Accordion>


I too have this problem with a normal LinkButton
Same problem here too, and it's driving me bonkers :(
I see you are not using panes inside the accordion. Is this because you only need one pane? I thought you'd need one pane for every GridViewConfused
In my project, I am using Panes and I'm still having issued. All the Panes are being loaded dynamically though, which I need to do that way. Any ideas out there?

All I have the solution, it dosen't make sence but it solves the problem

at the page Load create a pointer to the control for example

Dim btnAs Button =CType(Accordion1.Panes(0).FindControl("btnQuickSearch"), Button)

Where btnQuickSearch is the id of the button

Good Luck


This seems like a common problem.

The example above works for an accordion with only one pane. However, if I do the same to try and initialize controls in the second, or third pane it doesn't work. I can reference the controls in my code, however I still have to click a button twice to fire the event.

Does anyone have any thoughts on how to avoid this? Or, can I catch the accordion transition event (if there is one) and then initialize my controls for that pane in that event?

This one has me stumped.


I'm having almost the exact same issue. I am creating what is essentially a datagrid-accordion where each line of the control is an accordion panel. I managed to get sorting and paging to work, but they are outside the actual accordion control. I can't make the controls inside the accordion pane to trigger their appropriate event. At one point I was able to have them fire on the second click, but after adding a command name and command argument to the buttons, they don't do that anymore.

I would also like to be able to have a 'cancel' button that closes the panel, but nothing is working. The cancel button could be done with javascript, but no one seems to know how to do this. Are there no solutions to these problems? I don't want to have to make with a complicated work around where I have to create the buttons inside the accordions data bind event... its way more hassle than its worth.

Thanks


Yup I'm where you're at as well. It's a little silly that just getting buttons to work in an accordion can be so complex haha.

I have gotten buttons to work, but only when I manually create the accordionpanes and do the oninit() trick. That's not we want of course, there must be a way to wire up a databound accordion to get control events to fire. I don't know how to tap into an accordionpane's oninit function when they are created through databinding though, does anyone have a solution?

- Calvin


So far the best I can do is get the double click effect on a databound accordion. Add a empty panel and set its visibility to false, and you get the problems noted herehttp://forums.asp.net/t/1017782.aspx. But the fixes they talked about don't seem to work for the databound panels.

If I get any farther with a work around I will let you all know.


Ok, so what I came up with was to actually change the source code. Its not a lot to change, but its not 100% perfect.

Also, I can't take credit for this, because I gathered the combined changes required from various sources, but here it is:

TheAccordion Class needs to be changed from aWebControl to aCompositeControl.

source:here

And both theAccordion Class and theAccordion Panel Class need to use theINamingContainer.

source:here

Here is an example of the change:

was:public class Accordion : WebControl

is now:public class Accordion : CompositeControl, INamingContainer

Hope this helps some people.


I made the change but now clicking buttons makes the entire accordion disappear. I'm not positive it's due to changing the base to compositecontrol though, because I was fiddling with a ton of other stuff before I caught your post. It's way too late in my project to try to keep messing around with the control however, so it's back to old school repeaters for me.


CalZ:

I made the change but now clicking buttons makes the entire accordion disappear. I'm not positive it's due to changing the base to compositecontrol though, because I was fiddling with a ton of other stuff before I caught your post. It's way too late in my project to try to keep messing around with the control however, so it's back to old school repeaters for me.

I had that issue as well... where are you doing the databind?


I'm binding it in the markup:

<cc1:Accordion ID="AccordionResults" runat="server" DataSourceID="SqlDataSourceResults" SelectedIndex="-1" RequireOpenedPane="false" FadeTransitions="true" OnItemCreated="InitPanes" HeaderCssClass="accordionHeader" HeaderSelectedCssClass="accordionHeaderSelected" ContentCssClass="accordionContent" Width="800px">

And onItemCreated calls:

Protected Sub InitPanes(ByVal sender As Object, ByVal e As AjaxControlToolkit.AccordionItemEventArgs)

Dim myAccordionPane As AjaxControlToolkit.AccordionContentPanel = CType(e.AccordionItem, AjaxControlToolkit.AccordionContentPanel)
Dim workAroundLabel As New Label
workAroundLabel.Visible = False
myAccordionPane.Controls.Add(workAroundLabel)

End Sub


Well, before I make any suggestions, realize I am not an expert at this by any measure. But when I experienced the same symptoms, it was because I was Adding controls before I was binding the data (so adding controls to an accordion with no panes), or at least thats what I thought.

Looking at you're code, my only suggestion is that you remove the work around label and give it one last try.

Sorry I cant be of more help.

Monday, March 26, 2012

Conflict between OnError and OnAsyncPostBackError events

I am updating my application from ATLAS to Ajax RC.

All my pages are inherited from my own WebPage subclass page that implements an OnError event and I have included the Script Manager with the OnAsyncPostBackError property in the master pages of the application.

When an exception is thrown within an Update Panel the Onerror event captures the exception and I haven't found a way to setup the AsyncPostBackErrorMessage. An alert message appears with the text:


Sys.WebForms.PageRequestManagerServerException: An unknown error occurred while processing the request on the server. The status code returned from the server was: 500


Any suggestions...?


Thanks...Antonio

Try to capture asynchronous?post?back error as the follow.
?????ScriptManager.AsyncPostBackError += new EventHandler<AsyncPostBackErrorEventArgs>(ScriptManager_AsyncPostBackError);
Determine if it is asynchronous post back:
?????ScriptManager.IsInAsyncPostBack;
Get synchronous post back error message:
?????ScriptManager.AsyncPostBackErrorMessage;
Get asynchronous post back source:
?????ScriptManager.AsyncPostBackSourceElementID;
Wish the above can help you.

I am having the same issue... We have existing sites that uses a standard basepage the overrides the OnError to catch any page errors. It will log the error and then redirect to a nicely formatted error page to explain the error. This works fine, but when I am inside a AJAX call and I get an error, I also get the following error

Sys.WebForms.PageRequestManagerServerException: An unknown error occurred while processing the request on the server. The status code returned from the server was: 500

But if I remove my OnError Handler completely, then I will get the actual error in the javascript popup. How can I handle both the normal page errors and AJAX errors if just having the OnError seems to kill the AsyncPostBackError info?

Pat


changing UpdateMode from"Conditional" to "Always" solved my problem


I tried many ways to raise and catch the error with both OnError and OnAsyncPostBackError implemented. but no use. It always go to OnError handler.

Is someone suggests the complete code ... with master page, update panels on a page and onError and OnAsyncPostBackError events implemented?

Basically, I am looking to implement both handlers and distinguish to redirect Page request errors to OnError and Update panel requests errors to OnAsyncPostBackError;

Any help is appreciated in advance.


I found a way to do this ...

Put this snippet of code in your base Page codebehind ... this should capture every error that gets thrown.

1protected override void OnError(EventArgs e)2 {3 ScriptManager mgr = ScriptManager.GetCurrent(this);45 System.Exception ex =this.Server.GetLastError();67if (mgr.IsInAsyncPostBack)8 {9base.OnError(e);10 }11else12 {13this.Server.ClearError();1415base.OnError(e);1617 Response.Write(<html><head><title>Error</title></head><body>");18 Response.Write("<table class='Section'><tr class='SectionTitle'><td colspan='2'>Error Details</td></tr><tr><TD valign='top' class='FieldLabel' width='125px'>Error Message:</TD><td class='GenText'>");19 Response.Write(ex.Message);20 Response.Write("</TD></TR><TR><TD valign='top' class='FieldLabel'>Error Source:</TD><TD class='GenText'>");21 Response.Write(ex.Source);22 Response.Write("</TD></TR><TR><TD valign='top' class='FieldLabel'>Stack Trace:</TD><TD class='GenText'>");23 Response.Write(ex.StackTrace);24 Response.Write("</TD></TR><TR><TD colspan=\"2\"><a href=\"");25 Response.Write(Request.RawUrl);26 Response.Write("\">Return to previous page</a></td></tr></table></body></html>");27 Response.End();28 }29 }

Then in your master page (or whatever page) codebehind capture the AsyncPostBackError from the ScriptManager tag (making sure to hook the OnAsyncPostBackError in the aspx page to the ScriptManager1_AsyncPostBackError):

1protected void ScriptManager1_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)2 {3if (e.Exception.Data["ExtraInfo"] !=null)4 {5 ScriptManager1.AsyncPostBackErrorMessage =6 e.Exception.Message +7 e.Exception.Data["ExtraInfo"].ToString();8 }9else10 {11 ScriptManager1.AsyncPostBackErrorMessage ="The following error occurred: " + e.Exception.Message;13 }14 }


My updated code for handling OnError and OnAsyncPostBackError events ...

I took different approach like assigning event handlers early and then do accordingly. I have all my pages contain a Master Page and derived from Page Base ...MyAppPageBase

publicclassMyAppPageBase :Page
{
protectedoverridevoid OnInit(EventArgs e)
{
bool AttachPageErrorEventHandler =true;

// Determine if it is a page request, then only attach page error event handler
try
{
if (this.Page !=null &&
ScriptManager.GetCurrent(this.Page) !=null &&
ScriptManager.GetCurrent(this.Page).IsInAsyncPostBack)
{
// Note: We are not attaching any event handler for page error -->
this.Page.Error -=newEventHandler(MyAppPage_Error);
this.Page.Error +=newEventHandler(MyAppPage_UP_Error);
AttachPageErrorEventHandler =false;
}
}
catch { }

if (AttachPageErrorEventHandler)
{
this.Page.Error +=newEventHandler(MyAppPage_Error);
this.Page.Error -=newEventHandler(MyAppPage_UP_Error);
}
base.OnInit(e);
}

protectedvoid MyAppPage_Error(object sender,EventArgs e)
{
Exception exBase = Server.GetLastError().GetBaseException();

if (exBase.GetType().Name =="HttpRequestValidationException")
{
>>> Redirect to a page to show that you are using <script> tag as data; Malformed data
}
else// all other / generic exception
{

this.Context.AddError(exBase);
Server.ClearError();
Server.Transfer("~/Error.aspx");
Response.Flush();/*The line is added to cancel the event bubbleup */
Response.End();/*The line is added to cancel the event bubbleup */
}
}

protectedvoid TPPage_UP_Error(object sender,EventArgs e)
{
Exception exBase = Server.GetLastError().GetBaseException();
if (exBase.GetType().Name =="HttpRequestValidationException")
{
string str ="You have submitted the data with <script>tag or with malformed data";
Response.Write(string.Format("{0}|error|500|{1}|", str.Length, str ));
}
else// all other types of exception
{
Response.Write(string.Format("{0}|error|500|{1}|", exBase.Message.Length, exBase.Message));
}
}
}

so far it is working great!