在网上找到了一个叫做NewsArticles的dnn模块,作为文章管理还算不错,支持一级分类、用户投稿、权限控制、搜索等等,尤其是page的概念很不错,就是可以把一整篇文章分为几个小标题发表,每个标题内容作为一页,导航方式很人性化。不过美中不足的是没有提供分页功能,于是师域把这个光荣的任务交给了我,我也只好免为其难了。
NewsArticles的列表是通过用户控件ucListing.ascx实现的,我们要作的工作就是在这个控件中加入分页功能。分析源码发现:通过Repeater实现列表,数据使用了datareader读取。我写了一些代码,调试通过,但是运行的时候模块出错,信息如下:
Error loading module
DotNetNuke.ModuleLoadException: Unhandled Error Adding Module to ContentPane ---> System.Web.HttpException: Parser Error: External component has thrown an exception. ---> System.Web.HttpException: External component has thrown an exception. ---> System.Web.HttpCompileException: External component has thrown an exception. at System.Web.Compilation.BaseCompiler.ThrowIfCompilerErrors(CompilerResults results, CodeDomProvider codeProvider, CodeCompileUnit sourceData, String sourceFile, String sourceString) at System.Web.Compilation.BaseCompiler.GetCompiledType() at System.Web.UI.UserControlParser.CompileIntoType() at System.Web.UI.TemplateParser.GetParserCacheItemThroughCompilation() --- End of inner exception stack trace --- at System.Web.UI.TemplateParser.GetParserCacheItemInternal(Boolean fCreateIfNotFound) at System.Web.UI.TemplateParser.GetParserCacheItemWithNewConfigPath() at System.Web.UI.TemplateControlParser.GetReferencedType(TemplateControlParser parser, String virtualPath) at System.Web.UI.TemplateControlParser.GetUserControlType(String virtualPath) at System.Web.UI.TemplateControlParser.ProcessDirective(String directiveName, IDictionary directive) at System.Web.UI.TemplateParser.ParseStringInternal(String text) at System.Web.UI.TemplateParser.ParseString(String text, String virtualPath, String basePhysicalDir) --- End of inner exception stack trace --- at System.Web.UI.TemplateParser.ParseString(String text, String virtualPath, String basePhysicalDir) at System.Web.UI.TemplateParser.ParseFile(String filename, String virtualPath) at System.Web.UI.TemplateParser.Parse() at System.Web.UI.TemplateParser.GetParserCacheItemThroughCompilation() at System.Web.UI.TemplateParser.GetParserCacheItemInternal(Boolean fCreateIfNotFound) at System.Web.UI.TemplateParser.GetParserCacheItemWithNewConfigPath() at System.Web.UI.TemplateParser.GetParserCacheItem() at System.Web.UI.TemplateControlParser.CompileAndGetParserCacheItem(String virtualPath, String inputFile, HttpContext context) at System.Web.UI.TemplateControlParser.GetCompiledType(String virtualPath, String inputFile, HttpContext context) at System.Web.UI.UserControlParser.GetCompiledUserControlType(String virtualPath, String inputFile, HttpContext context) at System.Web.UI.TemplateControl.LoadControl(String virtualPath) at DnnForge.NewsArticles.NewsArticles.LoadControlType() at DnnForge.NewsArticles.NewsArticles.Page_Init(Object sender, EventArgs e) at System.Web.UI.Control.OnInit(EventArgs e) at System.Web.UI.UserControl.OnInit(EventArgs e) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.AddedControl(Control control, Int32 index) at System.Web.UI.ControlCollection.Add(Control child) at DotNetNuke.Skin.InjectModule(Control objPane, ModuleSettings ModuleSettings, PortalSettings PortalSettings) in G:\mywebs\DotNetNuke\admin\Skins\Skin.vb:line 600 --- End of inner exception stack trace ---
不知道原因出在哪里,希望大家指点一下,不胜感激。
ucListing.ascx源码:
<asp:Repeater ID="rptListing" Runat="server">
<ItemTemplate>
<asp:PlaceHolder ID="plhDayTop" Runat="server" Visible="False">
<table cellSpacing=1 cellPadding=0 width="100%" align=center border=0><tr><td class=articleTable>
<table cellSpacing=1 cellPadding=3 width="100%" border=0>
<tr align=left>
<td class=articleTopCell align=left><span class="NormalWhite"><%# DataBinder.Eval(Container.DataItem, "CreatedDate", "{0:D}") %></span></td>
</tr>
<tr>
<td class="articleContentCell">
</asp:PlaceHolder>
<table width="100%">
<tr>
<td><a href='<%# Page.ResolveUrl(NavigateUrl() & "&newsType=CategoryView&CategoryID=" & DataBinder.Eval(Container.DataItem, "CategoryID").ToString()) %>'><img src='<%# GetCategoryImage(DataBinder.Eval(Container.DataItem, "CategoryImage").ToString()) %>' border='0'></a></td>
<td class="Normal" align="left" width="100%">
<asp:HyperLink id="editLink" NavigateUrl='<%# GetEditUrl(DataBinder.Eval(Container.DataItem, "ArticleID").ToString()) %>' Visible="<%# IsEditable%>" runat="server"><asp:Image id="editLinkImage" AlternateText="Edit" Visible="<%#IsEditable%>" ImageUrl="~/images/edit.gif" Runat=Server/></asp:HyperLink>
<a href='<%# Page.ResolveUrl(NavigateUrl() & "&newsType=ArticleView&articleId=" & DataBinder.Eval(Container.DataItem, "ArticleID").ToString()) %>' class="articleTitle"><%# DataBinder.Eval(Container.DataItem, "Title") %></a> <br>
By <%# DataBinder.Eval(Container.DataItem, "AuthorFirstName") %> <%# DataBinder.Eval(Container.DataItem, "AuthorLastName") %> (<%# DataBinder.Eval(Container.DataItem, "AuthorUserName") %>) @ <%# DataBinder.Eval(Container.DataItem, "CreatedDate", "{0:t}") %> :: <a href='<%# Page.ResolveUrl(NavigateUrl() & "&newsType=CategoryView&CategoryId=" & DataBinder.Eval(Container.DataItem, "CategoryID").ToString()) %>' class="CommandButton"><%# DataBinder.Eval(Container.DataItem, "CategoryName") %></a> :: <a href='<%# Page.ResolveUrl(NavigateUrl() & "&newsType=ArticleView&articleId=" & DataBinder.Eval(Container.DataItem, "ArticleID").ToString() & "#Comments") %>' class='CommandButton' ><%# DataBinder.Eval(Container.DataItem, "CommentCount") %> Comments</a> :: <%# DataBinder.Eval(Container.DataItem, "NumberOfViews") %> Views
</td>
</tr>
<tr>
<td colspan="3">
<table cellSpacing=1 cellPadding=0 width="100%" align=center border=0><tr><td class=articleTable>
<table cellSpacing=1 cellPadding=3 width="100%" border=0>
<tr>
<td class="articleTextCell">
<span class="Normal"><%# DataBinder.Eval(Container.DataItem, "Summary") %></span>
</td>
</tr>
<tr runat="server" visible="<%# IsMultiPage(Container.DataItem) %>">
<td align="left" class="articleContentCell"><a href='<%# Page.ResolveUrl(NavigateUrl() & "&newsType=ArticleView&articleId=" & DataBinder.Eval(Container.DataItem, "ArticleID").ToString()) %>' class="CommandButton">Read More..</a></td>
</tr>
</table>
</TD></TR></TBODY></TABLE>
</td>
</tr>
</table>
<asp:PlaceHolder ID="plhSeperator" Runat="server" Visible="False"><hr></asp:PlaceHolder>
<asp:PlaceHolder ID="plhDayBottom" Runat="server" Visible="False">
</td>
</tr>
</table>
</TD></TR></TBODY></TABLE>
</asp:PlaceHolder>
</ItemTemplate>
</asp:Repeater>
<asp:label id="lblPageInfo2" runat="server" cssClass="TTTNormal"></asp:label>
<asp:datalist id="dlPager2" runat="server" repeatlayout="Flow" repeatdirection="Horizontal" cssclass="TTTNormal">
<selecteditemtemplate>
<asp:label id="Label2" CssClass="TTTNormalRed" runat="server">
<%# Ctype(Container.DataItem, PagerDetail).Text %>
</asp:label>
</selecteditemtemplate>
<itemtemplate>
<asp:hyperlink id="Hyperlink1" runat="server" navigateurl='<%# GetPagerURL(Container.DataItem) %>'>
<%# Ctype(Container.DataItem, PagerDetail).Text %>
</asp:hyperlink>
</itemtemplate>
</asp:datalist>
<asp:Label Runat="server" CssClass="NormalBold" ID="lblNoArticles" Visible="False"><br>No Articles Found.</asp:Label>
ucListing.ascx.vb源码:
Imports System.Web.UI.HtmlControls
Imports System.Web.UI.WebControls
Imports DotNetNuke
Namespace DnnForge.NewsArticles
Public MustInherit Class ucListing
Inherits PortalModuleControl
Protected WithEvents rptListing As System.Web.UI.WebControls.Repeater
Private _articleList As ArrayList = Nothing
Private _lastCreatedDate As DateTime = Null.NullDate
Private _categoryID As Integer = Null.NullInteger
Private _maxCount As Integer = Null.NullInteger
Private _maxAge As Integer = Null.NullInteger
Private _showApprovedOnly As Boolean = True
Private _startDate As DateTime = DateTime.Now
Protected WithEvents lblNoArticles As System.Web.UI.WebControls.Label
Private _keywords As String = Null.NullString
Protected WithEvents lblPageInfo2 As System.Web.UI.WebControls.Label
Protected WithEvents dlPager2 As System.Web.UI.WebControls.DataList
Private _req As HttpRequest
Private _currentStrip As Integer
Private _stripCount As Integer
Private _startItem As Integer
Private _endItem As Integer
Private _pagerItems As New ArrayList
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
End Sub
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If IsPostBack = False Then
End If
End Sub
Public Class PagerDetail
Public Text As String
Public Strip As Integer
End Class
Public ReadOnly Property StartItem() As Integer
' Beginning item of this page
Get
Return _startItem
End Get
End Property
Public ReadOnly Property EndItem() As Integer
' Ending item of this page
Get
Return _endItem
End Get
End Property
Public ReadOnly Property CurrentStrip() As Integer
' Current page being viewed
Get
Return _currentStrip
End Get
End Property
Public ReadOnly Property StripCount() As Integer
' Count of pages existing in this folder
Get
Return _stripCount
End Get
End Property
Public Sub BindListing()
Dim objArticleController As ArticleController = New ArticleController
Dim newPagerDetail As PagerDetail
Dim pagerCounter As Integer
' Grab current request context
_req = HttpContext.Current.Request
' Logic to determine paging
_currentStrip = CInt(_req("CurrentStrip"))
_articleList = objArticleController.GetArticleList(Me.ModuleId, CategoryID, MaxCount, MaxAge, ShowApprovedOnly, StartDate, Keywords)
Try
' Get the count of pages for this folder
_stripCount = CInt(10)
Catch ex As Exception
_stripCount = 1
End Try
' Do a little validation
If _currentStrip = 0 OrElse (_currentStrip > _stripCount) Then
_currentStrip = 1
End If
' Calculate the starting item
If _articleList.Count = 0 Then
_startItem = 0
Else
_startItem = (_currentStrip - 1) * _stripCount + 1
End If
' and calculate the ending item
_endItem = _startItem + _stripCount - 1
If _endItem > _articleList.Count Then
_endItem = _articleList.Count
End If
' Creates the pager items
' Create the previous item
If _stripCount > 1 AndAlso _currentStrip > 1 Then
newPagerDetail = New PagerDetail
newPagerDetail.Strip = _currentStrip - 1
newPagerDetail.Text = "Previous"
_pagerItems.Add(newPagerDetail)
End If
' Creates folder items
For pagerCounter = 1 To _stripCount
newPagerDetail = New PagerDetail
newPagerDetail.Strip = pagerCounter
newPagerDetail.Text = CStr(pagerCounter)
_pagerItems.Add(newPagerDetail)
Next
' Creates the next item
If _stripCount > 1 AndAlso _currentStrip < _stripCount Then
newPagerDetail = New PagerDetail
newPagerDetail.Strip = _currentStrip + 1
newPagerDetail.Text = "Next"
_pagerItems.Add(newPagerDetail)
End If
If (_articleList.Count = 0) Then
lblNoArticles.Visible = True
lblPageInfo2.Text = "Album contains nothing"
Else
dlPager2.DataSource = _articleList
If _currentStrip > 1 Then
dlPager2.SelectedIndex = _currentStrip
Else
dlPager2.SelectedIndex = 0
End If
dlPager2.DataBind()
lblPageInfo2.Text = "Page: "
rptListing.DataSource = _articleList
rptListing.DataBind()
lblNoArticles.Visible = False
End If
End Sub
Public Property CategoryID() As Integer
Get
Return _categoryID
End Get
Set(ByVal Value As Integer)
_categoryID = Value
End Set
End Property
Public Property MaxCount() As Integer
Get
Return _maxCount
End Get
Set(ByVal Value As Integer)
_maxCount = Value
End Set
End Property
Public Property MaxAge() As Integer
Get
Return _maxAge
End Get
Set(ByVal Value As Integer)
_maxAge = Value
End Set
End Property
Public Property ShowApprovedOnly() As Boolean
Get
Return _showApprovedOnly
End Get
Set(ByVal Value As Boolean)
_showApprovedOnly = Value
End Set
End Property
Public Property StartDate() As DateTime
Get
Return _startDate
End Get
Set(ByVal Value As DateTime)
_startDate = Value
End Set
End Property
Public Property Keywords() As String
Get
Return _keywords
End Get
Set(ByVal Value As String)
_keywords = Value
End Set
End Property
Private Sub rptListing_ItemDataBound(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptListing.ItemDataBound
If (e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim currentArticle As ArticleInfo = CType(e.Item.DataItem, ArticleInfo)
If Not (currentArticle Is Nothing) Then
If (e.Item.ItemIndex = 0) Then
' Render Top
'
CType(e.Item.FindControl("plhDayTop"), PlaceHolder).Visible = True
Else
Dim previousArticle As ArticleInfo = CType(_articleList(e.Item.ItemIndex - 1), ArticleInfo)
If Not (currentArticle.CreatedDate.Day = previousArticle.CreatedDate.Day) Then
' Render Top
'
CType(e.Item.FindControl("plhDayTop"), PlaceHolder).Visible = True
End If
End If
If (e.Item.ItemIndex + 1 = _articleList.Count) Then
' Render Bottom
'
CType(e.Item.FindControl("plhDayBottom"), PlaceHolder).Visible = True
Else
Dim nextArticle As ArticleInfo = CType(_articleList(e.Item.ItemIndex + 1), ArticleInfo)
If Not (currentArticle.CreatedDate.Day = nextArticle.CreatedDate.Day) Then
' Render Bottom
'
CType(e.Item.FindControl("plhDayBottom"), PlaceHolder).Visible = True
Else
CType(e.Item.FindControl("plhSeperator"), PlaceHolder).Visible = True
End If
End If
End If
End If
End Sub
Protected Function GetEditUrl(ByVal articleID As String) As String
Return NavigateURL() & "&newsType=SubmitNews&articleID=" & articleID
End Function
Protected Function IsMultiPage(ByVal dataItem As Object) As Boolean
Dim objArticle As ArticleInfo = CType(dataItem, ArticleInfo)
If (objArticle.PageCount > 0) Then
Return True
End If
Return False
End Function
Protected Function GetCategoryImage(ByVal image As String) As String
If (image <> "") Then
Return Me.PortalSettings.UploadDirectory & image
Else
Return Page.ResolveUrl("~/images/spacer.gif")
End If
End Function
End Class
End Namespace