Click here to monitor SSC

Damon Armstrong

Caffeine Induced Tirades about .NET and Life
And don't forget to check out my latest Simple-Talk articles
View Damon Armstrong's profile on LinkedIn      Add to Technorati Favorites      Add to Google     

Creating an ITemplate from a String

Published Wednesday, February 17, 2010 11:32 PM

I do a lot of work with control templates, and one of the pieces of functionality that I've always wanted is the ability to build a ITemplate from a string.  Throughout the years, the topic has come up from time to time, and I never really found anything about how to do it. though I have run across a number of postings from people who are also wanting the same capability.  As I was messing around with things the other day, I stumbled on how to make it work and I feel really foolish for not figuring it out sooner.

ITemplate is an interface that exposes a single method named InstantiateIn.  I've been searching for years for some magical .NET framework component that would take a string and convert it into an ITemplate, when all along I could just build my own.  Here's the code:


/// <summary>
///   Allows string-based ITempalte implementations
/// </summary>
public class StringTemplate : ITemplate
{

    #region Constructor
(s)

   
////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    ///   Constructor
    /// </summary>
    /// <param name="template">String based version of the control template.</param>
   
public StringTemplate(string template)
   
{
        Template
= template;
   
}

   
/// <summary>
    ///   Constructor
    /// </summary>
    /// <param name="template">String based version of the control template.</param>
    /// <param name="copyToContainer">True to copy intermediate container contents to the instantiation container, False to leave the intermediate container in place.</param>
   
public StringTemplate(string template, bool copyToContainer)
   
{
        Template
= template;
       
CopyToContainer = copyToContainer;
   
}

   
////////////////////////////////////////////////////////////////////////////////////////////

   
#endregion

    #region Properties

   
////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    ///   String based template
    /// </summary>
   
public string Template
    {
        get
;
       
set;
   
}

   
/// <summary>
    ///   When a StringTemplate is instantiated it is created inside an intermediate control
    ///   due to limitations of the .NET Framework.  Specifying True for the CopyToContainer
    ///   property copies all the controls from the intermediate container into instantiation
    ///   container passed to the InstantiateIn method.
    /// </summary>
   
public bool CopyToContainer
    {
        get
;
       
set;
   
}

   
////////////////////////////////////////////////////////////////////////////////////////////

   
#endregion

    #region ITemplate Members

   
////////////////////////////////////////////////////////////////////////////////////////////

    /// <summary>
    ///   Creates the template in the specified control.
    /// </summary>
    /// <param name="container">Control in which to make the template</param>
   
public void InstantiateIn(Control container)
   
{
        Control tempContainer
= container.Page.ParseControl(Template);
       
if (CopyToContainer)
       
{
           
for (int i = tempContainer.Controls.Count - 1; i >= 0; i--)
           
{
                Control tempControl
= tempContainer.Controls[i];
               
tempContainer.Controls.RemoveAt(i);
               
container.Controls.AddAt(0, tempControl);
           
}                
        }
       
else
       
{
            container.Controls.Add
(tempContainer);
       
}
    }

   
////////////////////////////////////////////////////////////////////////////////////////////

   
#endregion

}
//class

Converting a string into a user control is fairly easy using the ParseControl method from a Page object.  Fortunately, the container passed into the InstantiateIn method has a Page property.  One caveat, however, is that the Page property only has a reference to a Page if the container is located ON the page.  If you run into this problem, you may have to find a creative way to get the Page reference (you can add it to the constructor, store it in the request context, etc). 

Another issue that I ran into is that the ParseControl creates a new control, parses the string template, places any controls defined in the template onto the new control it created, and returns that new control with the template on it.  You cannot pass in your own container. Adding this directly to the container provided as a parameter in the InstantiateIn means that you end up with an additional "level" in the control hierarchy.  To avoid this, I added code in that removes each control from the intermediate container and places it into the actual container.  I am not, however, sure about the performance penalty associated with moving a bunch of control from one place to another, nor am I completely sure if doing such a move completely screws something up if you have a code behind, etc.  It seems to work when it's just a template, but my testing was ever-so-slightly shy of thorough when it comes to other crazy scenarios.  As a catch-all, I added a Boolean property called CopyToContainer that allows you to turn the copying on or off depending on your desires and needs.

by Damon
Filed Under:

Comments

No Comments
You need to sign in to comment on this blog
<February 2010>
SuMoTuWeThFrSa
31123456
78910111213
14151617181920
21222324252627
28123456
78910111213
How to Kill a Company in One Step or Save it in Three
 The majority of companies that suffer a major data loss subsequently go out of business. David Wesley... Read more...

Migrating from OCS 2007 R2 to Lync: Part 4
 Having migrated the rest of our users and legacy resources across, and start getting ready to... Read more...

Automated Script-generation with Powershell and SMO
 In the first of a series of articles on automating the process of building, modifying and copying SQL... Read more...

Seth Godin: Big in the IT Business
 Seth Godin has transformed our understanding of marketing in IT. He invented the concept of 'permission... Read more...

Using SQL Test Database Unit Testing with TeamCity Continuous Integration
 With database applications, the process of test and integration can be frustratingly slow because so... Read more...