by jasonrshaver
14. September 2011 21:39
If you are trying to integrate an ASP.NET server side control, especially one that requires use of a ScriptManager, you will find that the lack of a server side form element can put an end to your ambition. Getting around this is not that hard, here are the steps.
Changes to SkinBase
Add the following methods to your App_Code\SkinBase.cs file:
- #region Setup Controls Requiring ScriptManager
- private void SetupControlsRequiringScriptManager()
- {
- HtmlForm frm = this.ThisForm;
- if (frm == null)
- return;
-
- string randomId = Guid.NewGuid().ToString("N").Substring(0, 5);
- StringBuilder script = new StringBuilder();
- script.AppendFormat("<script type=\"text/javascript\" language=\"Javascript\">\n");
- script.AppendFormat(" function loadServerControl_{0}() {{\n", randomId);
-
- // script.Append(SetupServerControl(frm.FindControl("MyControlId") as WebControl));
-
- script.AppendFormat(" }}\n");
- script.AppendFormat(" $add_windowLoad(loadServerControl_{0});\n", randomId);
- script.AppendFormat("</script>\n");
-
- Page.ClientScript.RegisterStartupScript(this.GetType(), randomId, script.ToString());
-
- }
- private String SetupServerControl(WebControl control)
- {
- return SetupServerControl(control, String.Empty);
- }
- private String SetupServerControl(WebControl control, String customScript)
- {
- if (control == null)
- return string.Empty;
-
- HtmlForm frm = this.ThisForm;
-
- string MyControlId = control.ID;
- string MyContainerId = MyControlId + "_Panel";
- int MyOriginalIndex = FindParentIndex(control);
- var MyPlaceHolder = new Panel();
- MyPlaceHolder.ID = MyContainerId;
-
- Control MyParentControl = control.Parent;
- MyParentControl.Controls.Remove(control);
- MyParentControl.Controls.AddAt(MyOriginalIndex, MyPlaceHolder);
- frm.Controls.Add(control);
- control.Style["display"] = "none";
-
- StringBuilder script = new StringBuilder();
- script.AppendFormat(" var control_{0} = document.getElementById('{0}');\n", MyControlId);
- script.AppendFormat(" var panel_{0} = document.getElementById('{0}');\n", MyContainerId);
- script.AppendFormat(" if(control_{0} && panel_{1}) {{\n", MyControlId, MyContainerId);
- script.AppendFormat(" panel_{1}.appendChild(control_{0});\n", MyControlId, MyContainerId);
- script.AppendFormat(" control_{0}.style.display = '';\n", MyControlId, MyContainerId);
-
- if (String.IsNullOrEmpty(customScript) == false)
- script.AppendFormat(customScript, MyControlId, MyContainerId);
-
- script.AppendFormat(" }}\n");
- return script.ToString();
- }
- #endregion
And then add the SetupControlsRequiringScriptManager(); to your OnPreRender method:
- protected override void OnPreRender(EventArgs e)
- {
- if (HttpContext.Current != null)
- {
- //register the ScriptManager before loading controls or the ComponentArt menu won't work with AJAX pages
- CheckIfRequireScriptManager();
-
- if (!this.HasControls()) //Probably a web form so use the control management technique
- {
- if (m_Template.Content != null)
- {
- //No controls so html must come from RenderContents. Create a literal to contain RenderContents
- m_Template.Content.Controls.Add(ParseControl(CreateContent()));
- }
- this.Controls.Clear();
- this.Controls.Add(m_Template);
- // Now move the template child controls up to the page level so the ViewState will load
- while (m_Template.Controls.Count > 0)
- {
- this.Controls.Add(m_Template.Controls[0]);
- }
- }
-
- SetupControlsRequiringScriptManager();
- SetupMenu();
- }
-
- base.OnPreRender(e);
- }
Using The Result
Now, in your template.ascx, you can take your server side control and give it an ID, for example:
- <telerik:RadRotator ID="Rotator1" runat="Server" Width="750" Height="300"
- ItemHeight="300" ItemWidth="750" ScrollDirection="Down"
- DataSourceID="xmlDataSource1" ScrollDuration="1500"
- FrameDuration="3500" >
And add the following line to the SetupControlsRequiringScriptManager method right under the example comment:
- // script.Append(SetupServerControl(frm.FindControl("MyControlId") as WebControl));
- script.Append(SetupServerControl(frm.FindControl("Rotator1") as WebControl));
and you are done!
How Does It Work
This method works the same way as the ASP.NET Menu control workaround that is built into App_Code\SkinBase.cs, it creates a placeholder for the control and places the control into the HtmlForm, and tells it to not display (via the CSS display tag). Then, when the page is loaded into a browser, a script takes the control and puts it into the placeholder and sets its to display.
** Warning ** Webkit browsers, such as Chrome and Safari, do not handle the visibility changes of div elements the same as other browsers. If you are having trouble getting your controls to display in Webkit browsers when everything else is working fine, contact your control vendor for a workaround.
03737e39-7f60-4c31-988c-27567848454a|0|.0
Tags:
Blog