动态加载用户控件至DataList并为用户控件赋值
为了实现这个演示,Insus.NET使用通用的新闻例子,它类别(目录)以及文章。在一个页面,显示所有类别,每个目录下显示最新几条新闻。
效果如下:
目录是用DataList控件显示,而文章标题列表是一个用户控件显示,这个用户控件将动态被加入至DataList。
View Code
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound"> <HeaderTemplate> <table cellpadding="5" cellspacing="0" width="100%"> </HeaderTemplate> <ItemTemplate> <tr style="height: 30px; line-height: 10px;"> <td> $ </td> <td> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# "~/ArticleView.aspx?ID=" & Eval("Article_nbr")%>' ToolTip='<%# Eval("Subject")%>' Target="_blank"></asp:HyperLink> </td> <td> <%# objInsusDateTimeUtility.GetDateTime(Eval("PublicDate"), "yyyy-MM-dd")%> </td> </tr> </ItemTemplate> <FooterTemplate> </table> </FooterTemplate> </asp:Repeater>
View Code
View Code Imports System.Data Imports Insus.NET Partial Class AscxControls_ArticleList Inherits System.Web.UI.UserControl Implements ISetValue '继承接口 Dim objArticle As New Article() Protected objInsusDateTimeUtility As New InsusDateTimeUtility() Private _DataSource As Object Private _SubjectLength As Integer = 20 Public WriteOnly Property SubjectLength() As Integer Set(ByVal value As Integer) _SubjectLength = value End Set End Property Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load Data_Binding() End Sub '绑定数据至Repeater控件 Private Sub Data_Binding() Me.Repeater1.DataSource = _DataSource Me.Repeater1.DataBind() End Sub Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Dim objDrv As DataRowView = DirectCast(e.Item.DataItem, DataRowView) If e.Item.ItemType = ListItemType.AlternatingItem OrElse e.Item.ItemType = ListItemType.Item Then If e.Item.FindControl("HyperLink1") IsNot Nothing Then Dim LinkSubject As HyperLink = DirectCast(e.Item.FindControl("HyperLink1"), HyperLink) If objDrv("Subject").Length > _SubjectLength Then LinkSubject.Text = objDrv("Subject").Substring(0, _SubjectLength) & "..." Else LinkSubject.Text = objDrv("Subject").ToString() End If End If End If End Sub '实现接口 Public Sub SetValue(str As Object) Implements ISetValue.SetValue Me._DataSource = str End Sub End Class
上面用户控件中,有一个接口:
ISetValue
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Insus.NET { public interface ISetValue { void SetValue(object obj); } }
显示目录:
View Code
<asp:DataList ID="DataListCatalog" runat="server" RepeatColumns="2" RepeatDirection="Horizontal" DataKeyField="Catalog_nbr" OnItemDataBound="DataListCatalog_ItemDataBound"> <ItemTemplate> <div style="padding:2PX; height:25px; background-color:#cbfb25; font-weight:bold; line-height:25PX;"> <%# Eval("CatalogName")%> </div> <asp:PlaceHolder ID="PlaceHolderArticleList" runat="server"></asp:PlaceHolder> </ItemTemplate> </asp:DataList>
从数据库获取数据并绑定至目录的DataList控件。
View Code
Imports Insus.NET Partial Class Index Inherits System.Web.UI.Page Dim objCatalog As New Catalog() Dim objArticle As New Article() Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load If Not IsPostBack Then Data_Binding() End If End Sub Private Sub Data_Binding() objCatalog.IsActive = True Me.DataListCatalog.DataSource = objCatalog.GetByIsActive() Me.DataListCatalog.DataBind() End Sub End Class
下面是重点,就是OnItemDataBound事件,在这个事件中,需要找到asp:PlaceHolder控件,这个容器将用来加载用户控件。
Protected Sub DataListCatalog_ItemDataBound(sender As Object, e As DataListItemEventArgs) If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then '判断asp:PlaceHolder是否存在 If e.Item.FindControl("PlaceHolderArticleList") IsNot Nothing Then Dim ctllaceHolder As PlaceHolder = DirectCast(e.Item.FindControl("PlaceHolderArticleList"), PlaceHolder) '动态加载用户控件,并转换为接口。 Dim objuc As ISetValue = DirectCast(LoadControl("~/AscxControls/ArticleList.ascx"), ISetValue) '找到DataList控件的目录主键 objArticle.Catalog_nbr = Me.DataListCatalog.DataKeys(e.Item.ItemIndex) objArticle.Top = 2 '为用户控件赋值。 objuc.SetValue(objArticle.GetArticalTopByCatalog()) '加载用户控件。 ctllaceHolder.Controls.Add(objuc) End If End If End Sub