Rammesses:
I've currently trying to work up a suitable patch, tho' it looks like the fix will require a change to ExtenderBase class as well as the PopupControlExtender class.
Well, I managed to avoid needing to patch ExtenderBase, but it's a fairly hairy hack, involving changes to PopupExtenderControl.cs and PopupExtenderProperties.cs
In PopupExtenderControl.cs, add the following highlighted line to the thing method:
/// <summary>
/// OnLoad override to register a startup script for each PopupControl behavior
/// </summary>
/// <param name="e">arguments</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
foreach (PopupControlProperties popupControlProperties in TargetProperties)
{
// add a back reference to allow correct client id naming
popupControlProperties.Parent = this;
string key = string.Format(CultureInfo.CurrentCulture, "{0}_PopupControl_Close", popupControlProperties.ID);
string script = string.Format(CultureInfo.CurrentCulture, "var popupControlBehavior = Sys.Application.findObject('{0}'); if (popupControlBehavior) {{ popupControlBehavior.close(); }}", popupControlProperties.ID);
Page.ClientScript.RegisterStartupScript(this.GetType(), key, script, true);
}
}
Then in PopupExtenderProperties.cs, change the ID property as shown:
/// <summary>
/// Private control ID for the PopupControlBehavior
/// </summary>
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
[DisplayName("id")] // Note: Case is important here because it needs to match the "Atlas" default "id" property
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase", Justification = "Following Atlas pattern")]
public string ID
{
get
{
return string.Format(CultureInfo.CurrentCulture, "{0}_PopupControl", GetClientIDForTarget(TargetControlID));
}
set
{
// Do nothing
SuppressUnusedParameterWarning(value);
}
}
Finally, add the following property and helper method to the same file (PopupControlExtender.cs):
/// <summary>
/// Get / set our parent control
/// </summary>
/// <remarks>
/// i.e. the PopupExtender to which this PopupExtenderControl belongs.
/// </remarks>
internal Control Parent
{
get { return parentControl; }
set { parentControl = value; }
}
/// <summary>
/// Return the ClientID for the target control
/// </summary>
/// <remarks>
/// This relies on the Parent property of this PopupExtenderProperty
/// being set - if not, then the passed Target (Control) ID will be used.
/// This can cause problems if the Extender is used in repeaters, datagrids
/// or usercontrols, etc.
/// </remarks>
/// <param name="theTargetID"></param>
/// <returns></returns>
private string GetClientIDForTarget(string theTargetID)
{
string theClientID = theTargetID;
if (this.Parent != null)
{
// the parent of this Property will be the extender, so we need
// to jump up 2 levels to search for the target control
Control theControl = this.Parent.Parent.FindControl(theTargetID);
if (theControl != null)
{
theClientID = theControl.ClientID;
}
}
return theClientID;
}
The code should fall back to the current (broken ;-) ) functionality if the target control cannot be resolved. I guess the GetClientIDForTarget method could be a bit more agressive and recursively look for the target control - at the moment, it's a restriction that the target must be resolvable by the FindControl method of the parent of the extender.
Hope this helps.
Joel