SkinID can only be changed programmatically on or before OnPreInit - your only option to initiate this for a control is in the Page's OnPreInit.
Under normal circumstances, .Controls should be available at that stage.
In some cases, you need the following work-around for .master pages:
/*
* HACK: need to ensure master controls are instantiated first.
* */
MasterPage root = this.Master;
while (root.Master != null)
root = root.Master;
InvokeControlPreInit(Controls);
You can now have controls that need skinning implement some interface (IRuntimeSkinableControl) that allows them to assign their own skins:
private void InvokeControlPreInit(ControlCollection controls)
{
foreach (Control control in controls)
{
IRuntimeSkinableControl skinableControl;
if (null != (skinableControl = control as IRuntimeSkinableControl))
skinableControl.OnPreInit();
if (string.IsNullOrEmpty(control.SkinID) && control.Controls.Count > 0)
InvokeControlPreInit(control.Controls);
}
}
The control would apply it like so:
public class UserControl : System.Web.UI.UserControl, IRuntimeSkinableControl
{
public virtual void OnPreInit()
{
//assign this.SkinID
}
}