[asp.net]自定义控件(支持模板)2

接着上一篇,今天来做支持数据绑定的模板控件。 
使用支持数据绑定控件的一般模式为
private   void  Page_Load( object  sender, System.EventArgs e)
{
if ( ! this .IsPostBack)
{
this .tm.DataSource = new   string []{ " one " , " two " };
this .tm.DataBind();
}
}
先指定数据源,当确认数据源正确后调用DataBind方法进行数据绑定。然后就开始调用控件自己的DataBinding事件的处理程序,一般是OnDataBinding,在这个方法里对数据源进行操作。
前面已经有文章分析了数据源,可以想到,和一般的控件不同的是,支持模板的控件在进行数据绑定时需要多做一步,除了要把数据从数据源取出,还要把这些数据绑到模板上。
还有,数据源一般都是在初次加载页面时用到,回发后就不再提供数据源,而是依靠viewstate来维持。因此“把数据绑到模板”这一步操作要放到OnDataBinding进行(因为DataBind只被使用一次),而CreateChildControls则要做一些维持状态的工作。
先要做的,是准备一个接收数据源的属性。
然后要有一个“把数据绑到模板”的方法,就像下面这个
private   void  createTemplate()
{
if ( this .itemTemplate != null )
{
if ( this .dataSource != null )
{
// 计算创建了多少子模板
int  itemCount = 1 ;
// 只是为了方便而做的假设dataSource是string[]
foreach ( string  text  in  ( string []) this .dataSource)
{
ContainerControl cc
= new  ContainerControl(text);
this .itemTemplate.InstantiateIn(cc);
this .Controls.Add(cc);
itemCount
++ ;
}
// 保存数量到ViewState
this .ViewState[ " itemCount " ] = itemCount;
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate!1 " ));
this .ChildControlsCreated = true ;
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate! " ));
}
在上面的方法中,使用遍历数据源的方法来循环添加模板容器。不明白可以去看上一篇笔记。
viewstate可以维持模板内控件的状态,但是它却不负责创建控件,因此我们在这里保存了模板的数量itemCount,然后在CreateChildControls中创建itemCount个空模板,这样viewstate就可以给这些空模板附加上状态。
protected   override   void  CreateChildControls()
{
if ( this .itemTemplate != null )
{
int  itemCount = ( int ) this .ViewState[ " itemCount " ];
for ( int  i = 1 ;i < itemCount;i ++ )
{
ContainerControl cc
= new  ContainerControl( string .Empty);
this .itemTemplate.InstantiateIn(cc);
this .Controls.Add(cc);
}
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate! " ));
base .CreateChildControls();
}

然后就成了,下面是全部的代码。

using  System;
using  System.Web.UI;
using  System.ComponentModel;
using  System.Collections;
using  System.Data;

namespace  CC
{
///   <summary>
///  模板练习
///   </summary>

// 分析控件内的xml元素标记
[ParseChildren( true )]
public   class  TemplateControl : Control,INamingContainer
{
// 模板
private  ITemplate itemTemplate;

// 指定存放模板的容器控件
[TemplateContainer( typeof (ContainerControl)),Browsable( false )]
public  ITemplate ItemTemplate
{
get return   this .itemTemplate; }
set this .itemTemplate = value; }
}

// 数据源
private   object  dataSource;

[Browsable(
false )]
public   object  DataSource
{
get return   this .dataSource; }
set this .dataSource = value; }
}

///   <summary>
///  创建子控件,在这里创建的只是空壳,其内容根据ViewState来填充
///   </summary>
protected   override   void  CreateChildControls()
{
if ( this .itemTemplate != null )
{
int  itemCount = ( int ) this .ViewState[ " itemCount " ];
for ( int  i = 1 ;i < itemCount;i ++ )
{
ContainerControl cc
= new  ContainerControl( string .Empty);
// 将模板添加到专门的容器中
this .itemTemplate.InstantiateIn(cc);
// 将容器加到父控件中
this .Controls.Add(cc);
}
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate! " ));
base .CreateChildControls();
}

///   <summary>
///  当用户端调用DataBind,则表示准备好了数据源,此时可以开始创建子模板
///   </summary>
///   <param name="e"></param>
protected   override   void  OnDataBinding(EventArgs e)
{
// 确定服务器控件是否包含子控件。如果不包含,则创建子控件。
// this.EnsureChildControls();
this .createTemplate();
base .OnDataBinding (e);
}

// 手动创建子模板
private   void  createTemplate()
{
if ( this .itemTemplate != null )
{
// 当由类实现时,定义子控件和模板所属的 Control 对象。然后在内联模板中定义这些子控件。
// this.itemTemplate.InstantiateIn(this);
if ( this .dataSource != null )
{
// 计算创建了多少子模板
int  itemCount = 1 ;
// 只是为了方便而做的假设dataSource是string[]
foreach ( string  text  in  ( string []) this .dataSource)
{
ContainerControl cc
= new  ContainerControl(text);
// 将模板添加到专门的容器中
this .itemTemplate.InstantiateIn(cc);
// 将容器加到父控件中
this .Controls.Add(cc);
itemCount
++ ;
}
// 保存数量到ViewState
this .ViewState[ " itemCount " ] = itemCount;
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate!1 " ));
// 确认子模板创建完毕
this .ChildControlsCreated = true ;
}
else
this .Controls.Add( new  LiteralControl( " no itemtemplate! " ));
}

}

///   <summary>
///  容器控件,用来存放模板
///   </summary>
public   class  ContainerControl : Control,INamingContainer
{
private   string  text;

public   string  Text
{
get return   this .text; }
}

public  ContainerControl( string  text)
{
this .text = text;
}
}

}

完成了这个,接下来我们就可以自己写一个Repeater控件!

你可能感兴趣的:(asp.net)