自定义控件的构建(11)
这一节主要涉及到数据绑定控件,如GridView一类,对于ASP.NET Framework中的任何内容,都可以进行扩展,那么数据绑定控件也不例外
对于ListView之类,其都是用ItemTemplate格式化数据的,所以首先介绍一下 ItemTemplate的实现
ITemplate接口
其包含了一个InstantiateIn(),这个方法用于实例化控件中模板的内容,但不是必须实现它,ASP.NET Framework会自动的创建并调用它。
/// <summary>
/// 使用模板显示
/// </summary>
public class ItemTempletControl:CompositeControl{private ITemplate _itemTemplete;
[TemplateContainer(typeof(ItemTempletControl))]
[PersistenceMode(PersistenceMode.InnerProperty)]public ITemplate ItemTemplete
{get { return _itemTemplete; }set { _itemTemplete = value; }}public string Title { get;set; }public string Author{ get;set; }protected override void CreateChildControls(){_itemTemplete.InstantiateIn(this);
}
这个ItemTempletControl包含了一个返回ITemplete的ItemTemplete属性,可以看到,其被TemplateContainer,PersistenceMode两个特性修饰了
其中TemplateContainer表示包含这个模板的控件类型,PersistenceMode表示在页面中的保存方式,其值是个枚举值。
可以看一看,这个控件的声明方式
<custom:ItemTempletControl ID="ItemTemplet1" runat="server" ><ItemTemplete></ItemTemplete></custom:ItemTempletControl>
这个是我们很熟悉的模板,因为我们代码中将PersistenceMode设置为InnerProperty了。所有ItemTemplete作为一个子控件添加到了ItemTempletControl中
我们看一看这个控件是如何使用的,这里并不是我们的重点,因为后面还会讲到,所以也算做个伏笔。
页面定义:
<custom:ItemTempletControl ID="ItemTemplet1" runat="server" ><ItemTemplete><%#Container.Author %><%#Container.Title %></ItemTemplete></custom:ItemTempletControl>
后台编码
this.ItemTemplet1.Title = "123";this.ItemTemplet1.Author = "123";this.ItemTemplet1.DataBind();
这样,我们就会收到我们期望的结果了。这里用了<%#Container.Author %> 这种形式,Container引用了当前绑定容器,
这个例子中绑定容器就是ItemTempletControl。最后提醒的是不要忘了DataBind(),否则是看不出效果的。
默认模板
上面提到InstantiateIn()也可以不用实现,但那只是在不需要默认模板的情况下。
对上面的例子进行一些修改,使用默认模板
控件本身没有太大变化
public class ItemTempletWithDefalutControl : CompositeControl{private ITemplate _itemTemplete;
[TemplateContainer(typeof(ItemTempletWithDefalutControl))]
[PersistenceMode(PersistenceMode.InnerProperty)]public ITemplate ItemTemplete
{get { return _itemTemplete; }set { _itemTemplete = value; }}public string Title { get; set; }public string Author { get; set; }protected override void CreateChildControls(){if (_itemTemplete == null)_itemTemplete = new WithDefaultTemplet();
_itemTemplete.InstantiateIn(this);
}}
可以看到CreateChildControls()已经做了修改,它用于检测是否有ItemTemplet,没有的话则创建WithDefaultTemplet实例,这里的WithDefaultTemplet
就是我们自己定制的模板
public class WithDefaultTemplet : ITemplate{public void InstantiateIn(Control container){Label labtitle = new Label();
labtitle.DataBinding += new EventHandler(labtitle_DataBinding);
Label labAuthor = new Label();
labAuthor.DataBinding += new EventHandler(labAuthor_DataBinding);
container.Controls.Add(labtitle);container.Controls.Add(new LiteralControl("<br/>"));container.Controls.Add(labAuthor);container.Controls.Add(new LiteralControl("<br/>"));}void labAuthor_DataBinding(object sender, EventArgs e){Label lbl=(Label)sender;ItemTempletWithDefalutControl item = (ItemTempletWithDefalutControl)lbl.NamingContainer;lbl.Text = item.Author;}void labtitle_DataBinding(object sender, EventArgs e){Label lbl = (Label)sender;ItemTempletWithDefalutControl item = (ItemTempletWithDefalutControl)lbl.NamingContainer;lbl.Text = item.Title;}}
这个类就具体实现了InstantiateIn(),注意代码中创建的3个Label,当调用DataBind()时,会引发DataBinding()。
<custom:ItemTempletWithDefalutControl ID="WithDefalutControl1" runat="server"></custom:ItemTempletWithDefalutControl>
后台实例化:
this.WithDefalutControl1.Title = "123";this.WithDefalutControl1.Author= "234";this.WithDefalutControl1.DataBind();
很明显,ItemTempletWithDefalutControl()并未包含ItemTemplate,当浏览器显示页面时,ItemTemplet的内容由WithDefaultTemplet负责呈现
本文参考了《ASP.NET 3.5 揭秘》