I have run across an issue recently while incorporating AJAX into one of my applications. The issue demonstrates either my fundamental lack of understanding about how this technology works, or a problem in my implementation of it. I have created an bare-bones simple example to demonstrate what I'm seeing. I know how to remedy the problem, but I'd prefer the discussion center around *WHY* it's happening.
Here are the details. Consider a project with a default.aspx. That page has two controls, Button1 and PlaceHolder1. The project also contains as usercontrol, uc1.ascx, which simply contains a TextBox control, TextBox1. The click event of Button1 dynamically loads uc1 into the placeholder via the Page.LoadControl method. All I really want to do is set focus to to TextBox1 after the control is loaded. Without the UpdatePanel, I can do it two ways. I can either put TextBox1.Focus(); in UC1's page load event, or I can register a startup javascript to find the textbox and use its focus() method. Either way works fine. See example code below.
Now introduce UpdatePanel. Enclose Button1 and PlaceHolder1 in the same UpdatePanel. The result, no focus to the textbox. Move Button1 outside of the UpdatePanel, focus will work. Fundamental question is - WHY? Why does it matter where that button control is in relation to the Placeholder and UpdatePanel. I've done a lot of searching on this topic and I've found lots of questions but not many answers. Here's the code I'm using, to get focus to work correctly, move Button1 outside of the UpdatePanel:
Default.aspx
<%@dotnet.itags.org. Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:UpdatePanel ID="up1" runat="server">
<ContentTemplate>
<asp:Button ID="Button1" runat="server" Text="Load UC1" OnClick="Button1_Click" />
<br />
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Button1_Click Event:
protected void Button1_Click (object sender, EventArgs e)
{
Control ctrl = new Control();
this.PlaceHolder1.Controls.Clear();
ctrl = Page.LoadControl("uc1.ascx");
ctrl.ID = "DynamicCtrl";
this.PlaceHolder1.Controls.Add(ctrl);
}
uc1.ascx:
<%@dotnet.itags.org. Control Language="C#" AutoEventWireup="true" CodeFile="uc1.ascx.cs" Inherits="uc1" %>
UserControl 1 <br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
uc1.ascx.cs:
using System;
using System.Web.UI;
public partial class uc1 : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
//use either of these two lines in the example
//this.TextBox1.Focus();
ScriptManager.RegisterStartupScript(this, typeof(UserControl), "focus", "document.getElementById('DynamicCtrl_TextBox1').focus();", true);
}
}
OK, now I'm really annoyed and I'm punchy enough to reply to my own posts. In reading a multitude of UpdatePanel/focus related threads, I found a snipped of javascript code that I though I'd try. I inserted the following section of code in the default.aspx contained in my original post. First I inserted it in the head section of the page and that resulted in the dreaded 'Sys' is undefined message. Then I moved the javascript *below* the scriptmanager and the page loaded with no errors. Here's the code I now have inserted in default.aspx just before the end form tag:
<scripttype="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);
function pageLoaded(sender, args)
{
if (args.get_panelsUpdated().length > 0)
{
$get('DynamicCtrl_TextBox1').focus();
}
}
</script>
So here's what is making me punchy. I try the page in IE 6 & 7, no focus to the textbox. Try in FireFox, *FOCUS WORKING CORRECTLY*!! Now that's annoying. Could someone please take a stab at either reproducing what I'm seeing or possibly explaining it?? Thanks.
...BillH
I am developing a liking to responding to my own posts - makes me feel loved.
OK, so a few minutes ago I tried something that made my above scenario work. Don't know why, but now I have textbox focus in both IE and Firefox and the solution fits within the context of the project I'm working on. I don't need any startup scripts or Focus() methods on the textbox control.
What I did was create a public accessor for TextBox1 in the user contol codebehind as such:
public TextBox t
{
get
{
return this.TextBox1;
}
}
Then I added the following one line to the Button1 click event (after the dynamic control is added to the placeholder):
this.ScriptManager1.SetFocus(((uc1)ctrl).t.ClientID);Viola. Textbox focus in both IE7 and Firefox. No idea why, take it for what it's worth.
...BillH
Thank you so much!
I've been working on this issue for a while now... I couldn't get any of my TextBoxes inside any UpdatePanels to set focus.
The solution seems like you just have to set the focus like this:
this.ScriptManager1.SetFocus(TextBox1);
and voila it works.
Yep, that works when your textbox is on the page that's loaded. In my case, it was in a user control that was being dynamically loaded via button click events. At any rate, while your above sample would work when the control is within the same form as the ScriptManager, I would strongly suggest you explicitly pass the SetFocus method the ClientID of the control:
this.ScriptManager1.SetFocus (this.TextBox1.ClientID);
In that way if you go back and reuse this code somewhere and you have a textbox on a usercontrol or within some other dynamically loaded control it would still work.
...BillH
Many many thanks for your inputs! It really worked!
No comments:
Post a Comment