开发模板化服务器控件笔记(1)
2005-08-27 18:35 by 谷哥, 737 visits, 收藏, 编辑模板化控件提供将控制数据和UI分开,控制数据由模板控件提供模板控件本身不提供用户界面(UI),用户界面(UI)是由这个控件的内联模板提供.
开发一个模板化控件我们必须要:
1.创建模板化控件的时候为了使模板中的元素在页面控件树中有唯一的标记符,必须为模板控件实现System.Web.UI.INamingContainer接口。这个接口可以在你的模板控件下创建一个新的命名范围。
public class TemplateControl :Control ,INamingContainer
{...}
2.应用ParseChildren(true)元数据,告诉页面解析器解释该控件时将内部xml标记解析为属性而不是控件,此属性就是模板属性(ITemplate类型)(注:如果你的控件是从WebControl继承,就不需要应用该元数据,因为WebControl已经应用了该元数据属性)。
3.定义一个或多个System.Web.UI.ITemplate类型的属性模板。
4.在每个模板属性(ITemplate类型的属性)上必须定义ystem.Web.UI.TemplateContainerAttribute 类型的元数据属性以指出该属性使用哪种容器(注意:该容器必须实现了INamingContainer接口)
[TemlateContainer(typeof(TemplateContainer))]
public ITemplate TemleteItem
{...}
5.TemplateContainer元数据的参数是“容器控件”,页面中显式提供的用于作为用户界面的内联模板就实例化到该容器。(容器控件本身应该实现INamingContainer接口以保证模板中的元素在控件树中标记是唯一的)。
6.重载CreateChildControls方法以便在模板中创建子控件。
如果存在"模板属性"(ITemplate类型的属性)代码实现总体步骤为:
1.那么我们先创建一个容器控件的实例。
2.实例化模板中的元素并加入到容器中。
3.将这个容器添加到Controls集合中。
下面是具体实现细节:
第一步:
private Control myTemplateContainer = new TemplateContainer();
注意:如果要将模板控件本身作为容器控件则不需要这个实例化模板控件的过程.
第二步,是通过模板属性InstantiateIn方的法做到的.我们不需要实现这个方法,因为系统已经可以提供实现。
假设:TempleteItem是一个模板属性(public ITemplate TemplateItem {...})
那么第二步是这样实现的:
TemplateItem.InstantiateIn(myTemplateContainer)
注意:如果我们要将该模板控件作为该模板的容器那么语句为:
TemplateItem.InstantialteIn(this)
并且不需要有第三步的Controls.Add语句。
第三步:
Controls.Add(myTemplateContainer)
问:如果将模板化控件的自身作为这个控件模板容器的话,那么这条语句不需要(见上面红字标志的地方)。
7.重载OnDataBinding方法。
protected override void OnDataBinding(EventArgs e) {
EnsureChildControls();
base.OnDataBinding(e);
}
为什么要重载此方法呢?
因为:这样做是为了保证在页面计算模板内的任何元素的数据绑定之前模板中的元素都已经实例化好,否则在模板中的元素还没有实例化之前就如果我们执行模板中元素的绑定是不正确的。
这里我们简要的解释一下EnsureChildControls方法。
EnsureChildControls方法的功能是:确保当前的控件包含有子控件。 该方法首先检查服务器控件的ChildControlsCreated属性的值,若为false,则调用CreateChildrenControls方法创建子控件。