zoukankan      html  css  js  c++  java
  • 一起谈.NET技术,asp.net控件开发基础(16) 狼人:

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

      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一样,其绑定的数据不可能是一条的.

    public class ProductItem : WebControl, IDataItemContainer
    {
    private string _name;
    private decimal _price;

    public string Name
    {
    get { return _name; }
    set { _name = value; }
    }

    public decimal Price
    {
    get { return _price; }
    set { _price = value; }
    }

    public object DataItem
    {
    get
    {
    return this;
    }
    }

    public int DataItemIndex
    {
    get { return 0; }
    }

    public int DisplayIndex
    {
    get { return 0; }
    }
    }
    然后在主控件中如下实现
    private ProductItem _item;

    public string Name
    {
    get
    {
    EnsureChildControls();
    return _item.Name;
    }
    set
    {
    EnsureChildControls();
    _item.Name
    = value;
    }
    }

    public Decimal Price
    {
    get
    {
    EnsureChildControls();
    return _item.Price;
    }
    set
    {
    EnsureChildControls();
    _item.Price
    = value;
    }
    }
      (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.net控件开发基础(15)

    下一篇:asp.net控件开发基础(17)
  • 相关阅读:
    点击链接,取得href的值,但是不转向
    启动和停止MySQL服务
    QuickText for Notepad++
    otepad++ 配置 支持jquery、html、css、javascript、php代码提示
    windows 2008+IIS7+Mysql+PHP5.5 + FastCGI环境配置
    Jquery异步请求数据实例代码
    JS读取本地文件及目录的方法
    c#.net从ftp下载文件到本地
    怎样才能充分利用SQL索引
    jQuery EasyUI Datagrid性能优化专题
  • 原文地址:https://www.cnblogs.com/waw/p/2162800.html
Copyright © 2011-2022 走看看