在网上找到了一个叫做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源码:

<%@ Control language="vb" Inherits="DnnForge.NewsArticles.ucListing" CodeBehind="ucListing.ascx.vb" AutoEventWireup="false" Explicit="True" %>
<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
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.ObjectByVal 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.ObjectByVal 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 = 0Then
                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.ObjectByVal 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 NothingThen

                    
If (e.Item.ItemIndex = 0Then

                        
' 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.DayThen

                            
' 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.DayThen

                            
' 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 StringAs String

            
Return NavigateURL() & "&newsType=SubmitNews&articleID=" & articleID

        
End Function


        
Protected Function IsMultiPage(ByVal dataItem As ObjectAs Boolean

            
Dim objArticle As ArticleInfo = CType(dataItem, ArticleInfo)

            
If (objArticle.PageCount > 0Then

                
Return True

            
End If

            
Return False

        
End Function


        
Protected Function GetCategoryImage(ByVal image As StringAs String

            
If (image <> ""Then

                
Return Me.PortalSettings.UploadDirectory & image

            
Else

                
Return Page.ResolveUrl("~/images/spacer.gif")

            
End If

        
End Function


    
End Class


End Namespace