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