.NET Forum / ASP.NET / Building Controls / April 2006
Adding controls to EditableDesignerRegion/ITemplate in code.
|
|
Thread rating:  |
Christophe Peillet - 04 Apr 2006 09:05 GMT I have a base custom control called 'WebBox' that contains a single EditableDesignerRegion. The contents of this EditableDesignerRegion are stored in an ITemplate via a property name 'Content', and serialized as an InnerProperty.
This all works as expected, renders properly, etc., but I can't figure out how, in a control that inherits WebBox (such as AdvertisementWebBox, SearchWebBox, etc.) to add controls to the ITemplate in code on the Server Side. If I add things in the markup, as below, everything works fine (see inner property names 'Content').
<CompanyUI:WebBox ID="SearchWebBox" runat="server" IconWidth="0" SkinID="SearchBox" Title="Search" TitleVisible="True" Width="180px"> <Content> <div style="text-align: center"> <table border="0" cellpadding="0" cellspacing="0" style="width: 100%"> <tr> <td align="left" style="width: 130px" valign="top"> <CompanyUI:AdvancedTextBox ID="AdvancedTextBox1" runat="server" LabelPosition="Bottom" Width="130px"></CompanyUI:AdvancedTextBox></td> <td align="center" valign="top"> <CompanyUI:AdvancedButton ID="SearchButton" runat="server" Text="go" /></td> </tr> <tr> <td align="left" colspan="2" style="width: 130px" valign="top"> <CompanyUI:CompanyHyperLink ID="AdvancedSearchLink" runat="server" Description="" LinkLeaderCssClass="" LinkLeaderImageCssClass="" LinkLeaderImageUrl="" NavigateUrl="~/AdvancedSearch.aspx" TextResourceKey="AdvancedSearch">Advanced Search</CompanyUI:CompanyHyperLink></td> </tr> </table> </div> </Content> </CompanyUI:WebBox>
How can I do this in code in another specialized server control, though?
In the server control that inherits WebBox, I have tried the following, but with no success.
protected override void OnPreRender(EventArgs e) { // Call underlying OnPreRender method base.OnPreRender(e);
if (!(this.DesignMode)) { // Clear WebBox .Content control collection Control template = new Control(); base.Content.InstantiateIn(template);
// ToDo: How to add controls to an ITemplate in code?
template.Controls.Clear(); ... // Add controls to collection ... template.Controls.Add(...) ... } }
I want WebBox as a generic control with an empty ITemplate, and in specialized controls that inherit from it to add controls like Search boxes, link listings, etc.
Any help on this would be appreciated.
Steven Cheng[MSFT] - 04 Apr 2006 11:10 GMT Thank you for posting,
As for the Template based control in ASP.NET, the template property (ITemplate) can not be created like normal control(by adding new controls into Controls collection). If we want to dynamically populate an template and use it in any Template based control, we need to create a custom Template class and add our custom code logic in the Template's code. Here are the msdn reference described programmatically creating ASP.NET server control template:
#Creating Web Server Control Templates Dynamically http://msdn.microsoft.com/library/en-us/vbcon/html/vbtskcreatingwebservercon troltemplatesdynamically.asp?frame=true
#Creating Templates Programmatically in the DataGrid Control http://msdn.microsoft.com/library/en-us/vbcon/html/vbtskcreatingtemplatespro grammaticallyindatagridcontrol.asp?frame=true
Hope this helps.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Christophe Peillet - 04 Apr 2006 12:54 GMT After looking at these examples, I'm still a bit lost. I have made a class that implements ITemplate, but still do not see how I can get access to something similar to a ControlCollection to add objects inside the template at run time. The ITemplate class is included below.
The example you gave me has a bit of code in the InstantiateIn method (using a switch), but I don't see how this is relevant to my needs. I only have one template, and simply need to be able to insert (via code) any controls into it, via something like 'MyServerControl.Content.Controls.Add(x);' when .Content is the ITemplate (or, in this case, 'WebBoxTemplate'). Sorry to bother you with this again, but if you know something a bit closer to my situation it would help me a lot.
As always, thanks for your help,
using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.Design; using System.Web.UI.Design.WebControls; using System.ComponentModel; using System.ComponentModel.Design; using System.Drawing; using System.Globalization; using System.Drawing.Design; using System.Diagnostics; using System.Reflection; using CompanyName.EEE.Web.UI; using CompanyName.EEE.Web.UI.FormControls;
namespace CompanyName.EEE.Web.UI.WebBoxes { /// <summary> /// This class provides an implementation of the <see cref="T:ITemplate" /> /// interface for allowing access to the <see cref="T:ITemplate" /> and /// <see cref="T:EditableDesignerRegion" /> properties/methods in /// <see cref="T:WebBox" /> controls. /// </summary> public class WebBoxTemplate : ITemplate { #region Constructor
/// <summary> /// Initializes a new instance of the <see cref="WebBoxTemplate"/> class. /// </summary> public WebBoxTemplate() { } #endregion
#region Public Methods
/// <summary> /// When implemented by a class, defines the <see cref="T:Control" /> object /// that child controls and templates belong to. These child controls are /// in turn defined within an inline template. /// </summary> /// <param name="container">The <see cref="T:Control" /> object to contain /// the instances of controls from the inline template.</param> public void InstantiateIn(Control container) { // How to pass something at run-time to container.Controls ? }
#endregion
} }
Steven Cheng[MSFT] - 05 Apr 2006 10:33 GMT Thanks for your response,
Yes, I know your confusion. Actually, what I used to think is that you want to do what we do at design-time( add some controls into Template by editing the Templte's inline markup in aspx file). As for ASP.NET control template, at design-time it is persisted as markup string, at runtime, the ASP.NET will call the template's InInstantiateIn method which will parse and compile the template and build the template's control collection. Then, those controls will be add into a container control's controls collection.
So one means to dynamically add additional controls into Template is define custom template class, and we can completely programmatically create the template at runtime and assign it to our custom control's Template field.
Also, another means is do something on the Container control, just like the "ItemDataBound" or "RowDataBound" event of the DataGrid , GridView control. Generally after calling template's InInstantiateIn, we'll add the returned controls into a container control(such as the DataGridItem of DataGrid). So in your custom control, you can consider use such a container control to do the dynamic control adding or modifying.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Christophe Peillet - 08 Apr 2006 21:39 GMT Steven:
I understood the need to override the InstantiateIn method ... what I couldn't figure out is what code to put to be able to pass any number of controls to this method at run time.
Would something like this work (I don't have VS in front of me to know the exact signature of this method):
protected override void (?) InstantiateIn(ControlCollection controlsToAdd) { ... // And then add the contents of the passed ControlCollection into the container? }
My problem was handing the controls over to the InstantiateIn method ... I just didn't see a good way to do this. If I can, I would like to avoid other developers using my APIs or Framework from having to write 5 lines of code to add a control to my ITemplate based property. Do you have any ideas or code suggestions on how to do this in the InstantiateIn method?
As always, I appreciate your help and expertise on this.
Christophe
Steven Cheng[MSFT] - 10 Apr 2006 13:39 GMT Thanks for your response Christophe,
I haven't found any particular resource on write our custom Template class (override the InstantiateIn method). Also, I think you can consider the other approach I mentioned, create a container class which hold the controls intialized from the Template and we can throw some event (which contains eventARgument reference to that container) so that the control's user can use that event to customize the controls collection intialized from Template. And in those ASP.NET built-in controls, you can have a look at the Repeater control(also DataList) which use a container control (e.g the Repeater's RepeaterItem ....). You can use the reflector tool to inspect into its code, you'll find it create a RepeaterItem through the CreateItem function and then call initializeItem which internally call the template.InstantiateIn to parse the template controls, then raise some events to let the user to customize the controls collection.
here is the reference code from reflector:
=========================== private RepeaterItem CreateItem(int itemIndex, ListItemType itemType, bool dataBind, object dataItem) { RepeaterItem item1 = this.CreateItem(itemIndex, itemType); RepeaterItemEventArgs args1 = new RepeaterItemEventArgs(item1); this.InitializeItem(item1); if (dataBind) { item1.DataItem = dataItem; } this.OnItemCreated(args1); this.Controls.Add(item1); if (dataBind) { item1.DataBind(); this.OnItemDataBound(args1); item1.DataItem = null; } return item1; } ============================ Hope this helps.
Regards,
Steven Cheng Microsoft Online Community Support
==================================================
When responding to posts, please "Reply to Group" via your newsreader so that others may learn and benefit from your issue.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 Signature Get Secure! www.microsoft.com/security (This posting is provided "AS IS", with no warranties, and confers no rights.)
Alessandro Zifiglio - 10 Apr 2006 14:37 GMT hi Christophe, Have you tried to add the information via the ToolboxData Metadata attributes since these are applied to server controls (and to their members) to provide information that is used by design tools, the ASP.NET page parser, the ASP.NET run time, and the common language runtime. Something like the following should work well for you :
[ToolboxData("<{0}:WebBox runat=\"server\">" + "<Content>" + " <div style=\"text-align: center\">" + "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\" style=\"width: 100%\">" + "<tr>" + "<td> <CompanyUI:AdvancedTextBox ID=\"AdvancedTextBox1\" runat=\"server\" LabelPosition=\"Bottom\" Width=\"130px\"></CompanyUI:AdvancedTextBox></td>" + "</tr>" + "</table>" + "</div>" + "</Content>" + "</{0}:WebBox>"), Designer(typeof(SimpleContainerControlDesigner))] public class WebBox : CompositeControl {//definition for your webbox control}
When this control gets dropped in the page, the string passed to the MetaData attribute ToolboxData is rendered into the page as as part of your control, just as you want it. Atleast it seems to me this is what you are trying to achieve. This is just an example, but you get the idea. Have a good day.
Alessandro Zifiglio
>I have a base custom control called 'WebBox' that contains a single > EditableDesignerRegion. The contents of this EditableDesignerRegion are [quoted text clipped - 73 lines] > > Any help on this would be appreciated. Alessandro Zifiglio - 10 Apr 2006 15:22 GMT oops, my mistake, now that i read your post (a bit slower this time) it seems i have misread your post after all. The urls suggested by Steven Chen are correct and the last post he made should answer your question. My apologies :-) Regards, Alessandro Zifiglio
> hi Christophe, Have you tried to add the information via the ToolboxData > Metadata attributes since these are applied to server controls (and to [quoted text clipped - 110 lines] >> >> Any help on this would be appreciated.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|