zoukankan      html  css  js  c++  java
  • asp.net控件开发基础(16)

            上一篇说要对以前进行补充,那个补充就先留着吧.写总结比较累,所以这篇为第16篇,第15篇先留着

    这次我们继续讨论.主题是模板控件,模板控件将是复杂控件的起步

    1.asp.net内置的模板控件,了解模板控件

    如下图,以下为asp.net内置的模板控件



    上图的控件一方面是模板控件,另一方面又是数据绑定控件.这里我们暂且不讨论如何实现数据绑定.

    使用上面控件的话,应该熟悉控件存在着不同的模板,如下图Repeater控件的模板类型.



    在不同模板内你可以定义控件显示内容会呈现不同效果.典型的运用就是GridView,其呈现代码会是一个表格代码,而Repeater则是自定义的.其实其是内部已经实现了的,暂且先不管这些.下面一步步看下来如何实现.


    2.实现模板控件

    2.1简单实现模板控件(静态模板)

    (1)模板控件为特殊的复合控件
    ,你还是需要实现INamingContainer接口,因为在模板属性的内容是为子控件集合添加到模板控件中,为保证控件具有唯一标识符.其实现将在CreateChildControls方法中创建子控件.

    asp.net2.0中可以直接继续CompositeControl就可

    (2)定义控件属性

    模板属性为System.Web.UI.ITemplate 接口,此接口有一InstantiateIn 方法 将在下面分析

    上一篇我们说明了控件内部属性和控件的区别,模板并非控件而是属性,我们在属性浏览器中并未看到此属性,是因为我们为其加了元数据,作为内部属性使用

    定义模板属性方法如下

            //声明变量
            private ITemplate _itemTemplate;


            
    //属性
            [Browsable(false)]
            [TemplateContainer(
    typeof(Article))]
            [PersistenceMode(PersistenceMode.InnerProperty)]
            
    public ITemplate ItemTemplate
            
    {
                
    get return _itemTemplate; }
                
    set { _itemTemplate = value; }
            }

    这里我们认识到了一个TemplateContainer元数据,其与容器控件关联起来.Article为默认其自身控件,即默认将自身控件作为容器控件.

    (3).重写CreateChildControls方法

    此方法我们以前已认识过了,主要是为控件添加子控件

            protected override void CreateChildControls()
            
    {
                _itemTemplate.InstantiateIn(
    this);
            }


    这次我们要做的重点是认识ITemplate接口的InstantiateIn 方法,方法有一个Control参数,其为子控件和模板定义了一个容器控件(此处为其自身控件,下面看页面代码).如GridView和DataList控件都实现了自定义的容器控件.Repeater则是完全自定义的.这里暂且默认实现

    实现代码

    在模板内拖了一个label控件

        <custom:Article
            
    id="Article1"
            Runat
    ="server">
            
    <ItemTemplate>
            
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            
    </ItemTemplate>
        
    </custom:Article>   

    OK,你可以看一下效果了,当然你可以定义多个模板然后在多个不同模板内添加内容.我们来看下其控件树内容,如下图



    子控件有一个Label控件,非控件内容则以LiteralControl呈现.

    2.2实现动态模板

    当我们使用DataList控件时,往往在模板中动态的绑定一些数据,获取的这些数据则是ITemplate接口的InstantiateIn 方法中的容器控件.下面我们为控件定义属性,然后通过DataBind()方法和数据绑定表达式获取数据

    我们先先定义三个属性

    页面代码,注意要用DataBind()方法

        void Page_Load()
        
    {
            Article1.Title 
    = "Creating Templated Databound Controls";
            Article1.Author 
    = "Stephen Walther";
            Article1.Contents 
    = "Blah, blah, blah, blah";
            Article1.DataBind();
        }

    通过Container数据绑定表达式获取容器对象属性,此处容器对象为默认的Article



    如下实现

        <custom:Article
            
    id="Article1"
            Runat
    ="server">
            
    <ItemTemplate>
            
    <asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
            
    <%# Container.Title%><br />
            
    <%# Container.Author %><br />
            
    <%# Container.Contents %><br />
            
    </ItemTemplate>
        
    </custom:Article> 

    好了,到这里你就实现了一个简单的动态模板控件了.

    2.3实现默认模板

    在购书网站上我们常常看到由于图书太多的情况下,管理人员未能将图书封面发布到网站上,这时此书可能出现默认的图片"尚为此书添加图书封面"

    在一个具有模板的控件里,如果你未为控件添加模板属性的话,你可以通过实现默认模板来实现默认效果.

    (1)那你第一步要做的就是定义一个自定义模板.此模板需要实现ITemplate接口,实现InstantiateIn方法.看一下典型实现,如下代码

        public class ArticleDefaultTemplate : ITemplate
        
    {
            
    public void InstantiateIn(Control container)
            
    {
                Label lblTitle 
    = new Label();
                lblTitle.DataBinding 
    += new EventHandler(lblTitle_DataBinding);

                Label lblAuthor 
    = new Label();
                lblAuthor.DataBinding 
    += new EventHandler(lblAuthor_DataBinding);

                Label lblContents 
    = new Label();
                lblContents.DataBinding 
    += new EventHandler(lblContents_DataBinding);

                container.Controls.Add(lblTitle);
                container.Controls.Add(
    new LiteralControl("<br />"));
                container.Controls.Add(lblAuthor);
                container.Controls.Add(
    new LiteralControl("<br />"));
                container.Controls.Add(lblContents);
            }


            
    void lblTitle_DataBinding(object sender, EventArgs e)
            
    {
                Label lblTitle 
    = (Label)sender;
                ArticleWithDefault container 
    = (ArticleWithDefault)lblTitle.NamingContainer;
                lblTitle.Text 
    = container.Title;
            }


            
    void lblAuthor_DataBinding(object sender, EventArgs e)
            
    {
                Label lblAuthor 
    = (Label)sender;
                ArticleWithDefault container 
    = (ArticleWithDefault)lblAuthor.NamingContainer;
                lblAuthor.Text 
    = container.Author;
            }


            
    void lblContents_DataBinding(object sender, EventArgs e)
            
    {
                Label lblContents 
    = (Label)sender;
                ArticleWithDefault container 
    = (ArticleWithDefault)lblContents.NamingContainer;
                lblContents.Text 
    = container.Contents;
            }


        }

    在InstantiateIn方法中,定义了默认控件,并实现了默认绑定.在各自的数据绑定事件里通过容器控件(默认容器控件为ArticleWithDefault,此处还是没自定义容器控件,下面会介绍)的NamingContainer属性获取控件ID值.然后对控件进行赋值.

    (2)重写CreateChildControls方法

    当未定义模板属性时,则实现默认模板

            protected override void CreateChildControls()
            
    {
                
    if (_itemTemplate == null)
                    _itemTemplate 
    = new ArticleDefaultTemplate();
                _itemTemplate.InstantiateIn(
    this);
            }

    (3)页面代码

    下面实现效果跟2.2的定义的模板控件效果一样,这里只为说明默认模板的使用方法

        void Page_Load()
        {
            ArticleWithDefault1.Title = "Creating Templated Databound Controls";
            ArticleWithDefault1.Author = "Stephen Walther";
            ArticleWithDefault1.Contents = "Blah, blah, blah, blah";
            ArticleWithDefault1.DataBind();
        }

        
    <custom:ArticleWithDefault
            
    id="ArticleWithDefault1"
            Runat
    ="server" />

    2.4实现自定义容器控件

    上面我已经多次注明容器控件为默认自身控件,你可以通过自定义容器控件

    GridView控件会自动把数据以表格形式呈现,DataList控件有DataListItem ,Repeater则有RepeaterItem.

    这些控件实现数据绑定后,通常不是显示一条数据的,其控件都有一个Items属性,其表示项集合.

    每项数据都在其Item里面,看一下DataList绑定数据以后的控件树



    我们常常会需要在模板控件里以以下方式来获取模板内部控件

    如在DataList控件中

        protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
        
    {
            e.Item.FindControl(
    "");
            DataList1.Items[
    0].BackColor = System.Drawing.Color.Red;
        }


    通过此方法我们可以处理一些特殊的列和行.为实现上面效果,我们也可以为模板控件自定义容器控件

    (1)自定义容器控件类

    注意需要实现IDataItemContainer接口,就如DataList一样,其绑定的数据不可能是一条的.


    然后在主控件中如下实现



    (2)用TemplateContainer与模板属性关联起来

            [TemplateContainer(typeof(ProductItem))]
            [PersistenceMode(PersistenceMode.InnerProperty)]
            
    public ITemplate ItemTemplate
            
    {
                
    get return _itemTemplate; }
                
    set { _itemTemplate = value; }
            }

    (3)重写CreateChildControls方法

    注意了,此处模板的InstantiateIn方法不再是this了,而是自定义容器控件了,再用数据绑定表达式访问的将是ProductItem的数据(即自定义容器控件的数据)

            protected override void CreateChildControls()
            
    {
                _item 
    = new ProductItem();
                _itemTemplate.InstantiateIn(_item);
                Controls.Add(_item);
            }

    (4)页面代码

        void Page_Load()
        
    {
            Product1.Name 
    = "Laptop Computer";
            Product1.Price 
    = 1254.12m;
            Product1.DataBind();
        }


        
    <custom:Product
            id
    ="Product1"
            Runat
    ="Server">
            
    <ItemTemplate>
           
            Name: 
    <%# Eval("Name"%>
            
    <br />
            Price: 
    <%# Eval("Price""{0:c}"%> 
            
    </ItemTemplate>    
        
    </custom:Product>


    上面以Eval来绑定数据,也可以用Container表达式,如下图,其类型为ProductItem




    注意:当不是数据绑定控件时,则不能用Eval绑定语法,如上面的几个例子.大家可以测试一下.

    好了本次该讲的我想也讲完了,以上代码多为asp.net2.0揭密的例子

    本来上面代码完全可以在一个控件中实现的,但我把其分开来讨论,这样理解的更加深刻.上面都是模板控件基础.将为以后实现复杂效果打下基础.本次未涉及到数据绑定,下次我们继续讨论.希望对你有帮助,错误之处还请提出.

    示例代码下载
  • 相关阅读:
    POJ 1015 Jury Compromise【DP】
    POJ 1661 Help Jimmy【DP】
    HDU 1074 Doing Homework【状态压缩DP】
    HDU 1024 Max Sum Plus Plus【DP,最大m子段和】
    占坑补题。。最近占的坑有点多。。。
    Codeforces 659F Polycarp and Hay【BFS】
    Codeforces 659E New Reform【DFS】
    Codeforces 659D Bicycle Race【计算几何】
    廖大python实战项目第四天
    廖大python实战项目第三天
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/525666.html
Copyright © 2011-2022 走看看