A recommendation you'll see floating about the web is to put any custom user controls you create into the CONTROLTEMPLATES directory. However, it's like placing files into LAYOUTS – it's better to be in your own sub-folder. For RenderingTemplates though SharePoint apparently looks for them ONLY in the CONTROLTEMPLATES folder. So how can we get them into a subfolder?
Basically, you just need to put them there (as part of your Solution deployment, of course).
The web.config file for SharePoint contains a line that registers anything in or under the CONTROLTEMPLATES folder as "safe":
<SafeControl Src="~/_controltemplates/*" IncludeSubFolders="True" Safe="True" AllowRemoteDesigner="True" />
So we don't need a new SafeControl entry. You will get an error in your ULS logs:
Control template "MyFieldControl" does not exist.
But you can safely ignore this…
One other problem you'll have if you're doing this in a custom field (and perhaps other locations – I haven't tested) is verifying that your custom UI controls exist. Since SharePoint "can't find" your template, you'll have a problem. Most sample custom fields you'll find floating around the web contain code something like this in the CreateChildControls method of the control display page:
ddlLookup = (DropDownList)(TemplateContainer.FindControl("ddlLookup"));
if (ddlLookup == null)
{
throw new ArgumentException("ddlLookup is null. Corrupted
LookupControl.ascx file.");
}
All you need to do is explicitly load the field's user control, load the TemplateContainer control (which is your RenderingTemplate) and then search recursively for your UI control by ID:
TemplateContainer templateContainer = new TemplateContainer();
Control ctl = (Control)Page.LoadControl
("~/_controltemplates/MyField/ MyField_UserDisplay.ascx");
templateContainer.Template = ((RenderingTemplate)ctl.Controls[0]).Template;
Controls.Add(templateContainer);
ddlLookup = (DropDownList)FindChildControlRecursive(this, "ddlLookup");
if (this.phDynamicControls == null)
{
throw new ArgumentException("ddlLookup is null. Corrupted
LookupControl.ascx file.);
}
Note: the FindChildControlRecursive method simply iterates through the control hierarchy starting at the specified control (first parameter – this) looking for a control with the ID specified in the second parameter (ddlLookup).