I have a page for entering weekly donations. Most churches do this in a large batch, so the page is designed to be very easy to use: the tab order is very predictable, you can press the Enter key when you have entered all the necessary information, etc. Unfortunately, when I add an UpdatePanel and the AnimationExtender to this page, I lost a critical usability feature: the page did not set the focus to the proper control.
This is one of those problems that is well documented on the web, but not well solved. I found my answer here, in the midst of a lot of incorrect suggestions. Whet I have done is added an AnimationExtender to the TextBox that I want to have control. That AnimationExtender uses the OnLoad animation to set the focus. It's a little kludgy, it would be nice if the UpdatePanelAnimationExtender did it correctly in the first place.
But what's really nice is that I was able to hide the code in a custom control I had already written. The UpdatePanelAnimationExtender is complex to specify, and requires some javascript to make it all work. I had already encapsulated all of that into a composite control that I could just drop onto my page thus:
<mypeople:UpdateAnimation ID="updateAnimation" runat="server" AnimationTargetID="wholePage" UpdatePanelID="upnlContent" FocusControlID="donorLookup" />
I added the FocusControlID attribute, and added some code to generate the necessary controls and javascript:
protected override void CreateChildControls() { ... other code for the update panel // If there is a FocusControlID, add an extender to set the focus focusAE = null; if (!String.IsNullOrEmpty(FocusControlID)) { UpdatePanel upnl = Page.MuchBetterFindControl(UpdatePanelID); focusAE = new AjaxControlToolkit.AnimationExtender { TargetControlID = FocusControlID, Animations = " ", }; upnl.Controls[0].Controls.Add(focusAE); } // if ... code to build the page } // CreateChildControls protected override void OnPreRender(EventArgs e) { if (!String.IsNullOrEmpty(FocusControlID)) { Control theControl = NamingContainer.FindControl(FocusControlID); String controlID = FocusControlID; if (theControl != null) { if (theControl is PartyLookup) { controlID = ((PartyLookup)theControl).TextBoxClientID; } else { controlID = theControl.ClientID; } // if } // if js += "\nfunction OnLoad_FocusField() { UpdateExtenderFocusField('" + controlID + "'); }"; } // if } // OnPreRender
The method MuchBetterFindControl is from here. It searches the hierarchy of control for the control with the indicated ID.
An interesting note: I cannot create the UpdatePanelAnimationExtender inside the UpdatePanel, but I have to create the focus control's AnimationExtender inside the UpdatePanel. So, in the code for CreateChildControls, I make sure to add the extender to the UpdatePanel's controls, not to those of the composite control.
All in all, this turned out to be a nifty, relatively clean solution to a problem that remains unsolved in most of the places I saw it on the Internet. If you would like the code, email me and I will bundle up the pieces for you.
No comments:
Post a Comment