创建带模板的用户控件






4.77/5 (23投票s)
本文将介绍如何创建自己的、带有模板的 Repeater 控件。
引言
现代 Web 编程技术 ASP.NET 提供了许多工具和控件,可以快速开发 Web 应用程序。例如,Repeater
控件是一个非常简单且强大的控件,可以在短时间内将集合数据渲染到网页中。想象一下,如果您在经典 ASP 或 PHP 中要做同样的事情,您可能需要在 ASP 中编写一个包含 HTML 和服务器脚本的循环。ASP 和 ASP.NET 的第一个区别是 HTML 和服务器脚本的分离。微软提供了许多控件供您使用,例如:Repeater
、DataGridView
、DataList
等。在本文中,我将介绍如何创建这种模板化数据控件。
选择合适的场景
每次都创建自定义控件都是一种时间上的消耗。此外,它可能无法在所有场景下得到妥善的测试。选择像 DataReader
这样由微软本身提供和测试的控件,始终是最佳方法。然而,在某些场景下,我们可能需要更好的功能和控件定制。在这种情况下,我们会选择 UserControl
[或] CustomControl
开发。
在本文中,我将介绍一个典型的 DataRepeater
开发。即使 ASP.NET 中已经提供了这个控件,我们仍然要创建一个类似 Repeater
的控件(Repeating Repeater
),因为我们已经熟悉 Repeater
控件的功能及其模板,所以很容易理解。
规划控件
由于我们将创建一个类似 DataRepeater
的控件,所以关于控件的规划也很容易。我将只更改控件的名称。控件的名称是 MyRepeater
,它包含以下四个模板:
- Header 模板
- Footer 模板
- Item 模板
- Alternate item 模板
我们已经知道,Header 和 Footer 应该只渲染一次,而 Item 模板和 AlternateItemTemplate
的数量应该等于 DataSource
中项目的数量。
规划 DataSource
与 Repeater
一样,我们的控件也应该支持大多数通用类型,如下所示:
DataTable
数据视图
列表
Collection
ArrayList
数组
不要纠结于如何在控件内部处理所有上述数据类型。这真的很简单。所有上述数据类型都内部实现了 IEnumerable
,所以如果我们为 IEnumerable
开发一个控件,它将支持所有上述数据源。
重要数据类型
我们将使用以下重要数据类型来开发我们自己的 Repeater
,请参阅 MSDN 以获取这些类型的详细描述:
ITemplate
IEnumerable
INamingContainer
IDataItem
Control
创建用户控件
创建一个名为 MyRepeater.ascx 的新用户控件,并在 Default.aspx 中引用它。因此,default.aspx 和 MyRepeater.ascx 将如下所示:
MyRepeater.ascx
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="MyRepeater.ascx.cs" Inherits="MyRepeater" %>
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Src="MyRepeater.ascx" TagName="MyRepeater" TagPrefix="myOwn" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<myOwn:MyRepeater ID="MyRepeater1" runat="server">
</myOwn:MyRepeater>
</div>
</form>
</body>
</html>
创建模板
默认情况下,UserControl
内部没有任何模板,所以我们必须创建 public
属性来启用 UserControl
的模板。在 UserControl
内部创建以下四个 public
属性:
MyRepeater.ascx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections;
public partial class MyRepeater : System.Web.UI.UserControl
{
private ITemplate _ItemTemplate;
private ITemplate _AlternateItemTemplate;
private ITemplate _HeaderTemplate;
private ITemplate _FooterTemplate;
private IEnumerable _DataSource;
protected void Page_Load(object sender, EventArgs e)
{
}
[TemplateContainer(typeof(SimpleTemplateItem))]
public ITemplate ItemTemplate
{
get { return _ItemTemplate; }
set { _ItemTemplate = value; }
}
[TemplateContainer(typeof(SimpleTemplateItem))]
public ITemplate AlternateItemTemplate
{
get { return _AlternateItemTemplate; }
set { _AlternateItemTemplate = value; }
}
[TemplateContainer(typeof(SimpleTemplateItem))]
public ITemplate HeaderTemplate
{
get { return _HeaderTemplate; }
set { _HeaderTemplate = value; }
}
[TemplateContainer(typeof(SimpleTemplateItem))]
public ITemplate FooterTemplate
{
get { return _FooterTemplate; }
set { _FooterTemplate = value; }
}
}
ITemplate
:这是 ASP.NET 提供的接口,用于保存特定的模板内容。TemplateContainer
:此属性用于提供模板内容的类型。
对于每个模板,运行时都必须创建一个 UserControl
实例来保存内容。例如,如果您的 DataSource
有 100 条记录,则内部将创建 100 个模板实例。我们需要创建另一个 UserControl
来将每个模板渲染到其中。这个控件称为模板容器控件。创建类/控件如下:
SimpleTemplateItem.cs
public class SimpleTemplateItem :
Control, System.Web.UI.INamingContainer, IDataItemContainer
{
private object _CurrentDataItem;
public SimpleTemplateItem(object currentItem)
{
_CurrentDataItem = currentItem;
}
#region IDataItemContainer Members
public object DataItem
{
get { return _CurrentDataItem; }
}
public int DataItemIndex
{
get { throw new Exception
("The method or operation is not implemented."); }
}
public int DisplayIndex
{
get { throw new Exception
("The method or operation is not implemented."); }
}
#endregion
}
INamingContainer
:这是一个Marker
接口 — 它没有任何方法或属性 — 它只是为了在运行时提供控件 ID。IDataItem
:IDataItem
的属性用于相对于模板实例保存DataSource
的单个项目。
添加代码以渲染模板
到目前为止,我们已经创建了一个具有四个模板属性的 UserControl
,以及另一个 UserControl
(模板容器)来在其上渲染模板。现在我们需要添加代码逻辑来渲染模板。ITemplate
接口内部有一个名为 InstantiateIn
的方法,用于将模板内容渲染到所需的控件中。将以下代码添加到 myrepeater
类的 databind
方法中,这将把模板添加到 UserControl
中。
MyRepeater.ascx.cs [Databind 方法]
public override void DataBind()
{
//Rendering Header template into current control
AddTemplateAsControl(HeaderTemplate, null);
IEnumerator ie = DataSource.GetEnumerator();
bool renderAlternateTemplate = false;
while (ie.MoveNext())
{
if (renderAlternateTemplate && AlternateItemTemplate != null)
{
AddTemplateAsControl(ItemTemplate, ie.Current);
}
else if (AlternateItemTemplate != null)
{
AddTemplateAsControl(AlternateItemTemplate,ie.Current);
}
else
{
//don't render anything
}
renderAlternateTemplate = !renderAlternateTemplate;
}
//Rendering footer template into current control
AddTemplateAsControl(FooterTemplate, null);
//Always better to call base class implementation
base.DataBind();
}
private void AddTemplateAsControl(ITemplate anyTemplate,object cuurentItem)
{
SimpleTemplateItem templateContentHolder = new SimpleTemplateItem(cuurentItem);
anyTemplate.InstantiateIn(templateContentHolder);
this.Controls.Add(templateContentHolder);
}
测试 MyRepeater
要测试 Repeater
,请创建任何 DataSource
并将其绑定到 UserControl
。下面是测试 Repeater
的示例代码。
Default.aspx
<myOwn:MyRepeater ID="MyRepeater1" runat="server">
<HeaderTemplate>
Customer List:
<table border="1">
<tr><th>Id</th><th>Name</th><th>Location</th></tr>
</HeaderTemplate>
<ItemTemplate>
<tr style="background-color:gold">
<td><%#DataBinder.Eval(Container.DataItem,"Id") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"Name")%></td>
<td><%#DataBinder.Eval(Container.DataItem,"Location") %></td>
</tr>
</ItemTemplate>
<AlternateItemTemplate>
<tr><td><%#DataBinder.Eval(Container.DataItem,"Id") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"Name")%></td>
<td><%#DataBinder.Eval(Container.DataItem,"Location") %></td>
</tr>
</AlternateItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</myOwn:MyRepeater>
Default.aspx.cs
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<Customer> customerList = new List<Customer>();
customerList.Add(new Customer("Prem", "New york"));
customerList.Add(new Customer("Jhon", "Amsterdam"));
customerList.Add(new Customer("Peter", "London"));
customerList.Add(new Customer("Mani", "Chennai"));
customerList.Add(new Customer("Paul", "Paris"));
MyRepeater1.DataSource = customerList;
MyRepeater1.DataBind();
}
}
public class Customer
{
private string _Name;
private Guid _Id;
private string _Location;
public Customer(string name, string location)
{
this.Name = name;
this.Location = location;
this.Id = Guid.NewGuid();
}
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public Guid Id
{
get { return _Id; }
set { _Id = value; }
}
public string Location
{
get { return _Location; }
set { _Location = value; }
}
}
结论
我希望您已理解如何开发自己的模板化控件,例如 DataGrid
、DataList
等,并添加自己的功能。如果不需要任何额外的功能,也可以使用现有的 RepeaterItem
类,而不是 SimpleTemplateItem
类。我们创建的控件非常轻量级,就像普通的 Repeater
一样。如果需要,您还可以添加一些额外的功能,如分页、排序等。