复合控件
继承CompositeControl
布局
实现INamingContainer接口
INamingContainer是一个标记接口,没有任何属性方法
提供一个受保护的虚方法实现控件的初始化
加入控件Container.Controls.add
提供一个受保护的虚方法添加容器控件AddContainer(Container con)
通过EnsureChildControls检查bool ChildControlsCreated避免多次创建组件
在创建子控件后要把ChildControlsCreated = true;
tagkey来确定要包含整个自定义控件的HTML元素
该控件重写
get (return HtmlTextWriterTag.Table;)
RenderContrnts(HtmlTextWriter writer)
writer.RenderBeginTag()
RenderContainer(Container,writer)
RenderContainer(Container,writer)
writer.RenderEndTag()
子控件属性
public virtual string PayText
{
get
{
EnsureChildControls();
return PayLabel.Text;
}
set
{
EnsureChildControls();
PayLabel.Text = value;
}
}
子控件引发Command事件
private static readonly objectiveCommandEventKey = new object();
public event CommandEventHandle Command
{
add {Events.AddHandler(CommandEventKey,value);}
remove {Event.RemoveHandler(CommandEventKey,value);}
}
protected virtual void OnCommand(CommandEventArg e)
{
CommandEventHandler handler = Event[CommandEventKey] as CommandEventHandler;
if (handler != null) handler(this e);
RaiseBubblerEvent(this,e);
}
CommandEventArgs 事件数据类为了保持命令名称和命令参数,该类公开了两个属性CommandName和CommandArgument
将CommandEventArgs传给RaiseBubblerEvent方法,该方法把子控件的事件提升为父控件的事件
potected virtual void RaisePostBackEvent(string EvnentArgument)
{
...
CommandEventArgs e = new CommandEventArgs(CommandName, CommandArgument);
OnCommand(e);
}
Control类公开了OnbubbleEvent方法,符合控件需要重写。
protected override bool OnBubbleEvent(object source, EventArgs args)
首先检测是否捕获的是Command事件
CommandEventArgs ce = arg as CommandEventArgs;
if (ce != null && ce.CommandName = "ValidateCreditCard")
这个过程可以获取子控件信息,构建事件数据类,触发事件
CompositeControl提供了必须支持的特性
1)重写Controls集合
2)实现INamingInterface
3)重写DataBind方法
4)实现ICompositeControlDesignerAccessor接口。该接口定义了一个ReCreateChildControls方法
5)在实现Render前,处于设计模式时,可重写Render方法来调用EnsureChildControls方法
重写Controls集合
public override ControlCollection Control
{
get{
EnsureChildControl();
return base.Controls;
}
}
INamingContainer为ClientID和UniqueID属性设置唯一值
子控件继承了Control类的NamingContainer属性,该属性指向子控件实现了INamingContainer接口的上级父控件