views:

67

answers:

3

Hi,

I have a page on my ASP.NET site that has a Repeater control to show posts from members of the site.

At the moment I am storing the data for the posts in an XML file and then caching it within the site inside custom objects.

So I have:

public class MemberPost
{
    public string Title { get; set; }
    public string Text { get; set; }
    public string Name { get; set; }
    public DateTime Date { get; set; }
    public List<string> Pictures { get; set; }
}

And:

public class MemberPosts : List<MemberPost>
{

}

I'm able to set the data source of the repeater to an instance of MemberPosts and it all works as expected, but I want to add paging for when more posts are added.

All the examples I find seem to involve having the data to be paged in a database - is there any way I can bind the repeater or another similar control to my in-memory MemberPosts collection and have it implement paging for me?

I'm using VS2010 / .NET 3.5, but can switch to 4.0 if necessary as I have that on my server.

Thanks.

+4  A: 

http://msdn.microsoft.com/en-us/library/bb358985.aspx

http://msdn.microsoft.com/en-us/library/bb503062.aspx

those are the 2 methods in IEnumerable you need.

You got

yourList.Skip(5).Take(5)

to show the second page of 5 items.

Alexander
I would need to add all the support then for displaying a new page etc using querystrings and page numbers etc?I really just want to let ASP.NET handle all the paging for me and just put my data into some kind of format that will allow me to page it.I'll go down that route though if I need to......
Michael
ASP.NET probably doesn't have any paging control. ASP.NET MVC doesn't. When I was studying it, one of the examples of extension methods was a method that output HTML of pages, and all controllers had implicit paging.
Alexander
Thanks, pulled my finger out and did the code below........
Michael
+3  A: 

Using the idea of Skip and Take, I put together the following and it was pretty easy and works a treat thanks :-)

protected void Page_Load(object sender, EventArgs e)
{
    IEnumerable<MemberPost> posts = from post in MemberPostCacher.Instance.Posts
                                    orderby post.Date descending
                                    select post;

    memberPostsRepeater.DataSource = GetPageMemberPosts(posts);
    memberPostsRepeater.DataBind();
}

private IEnumerable<MemberPost> GetPageMemberPosts(IEnumerable<MemberPost> posts)
{
    int totalNumberOfPosts = posts.Count();
    int pageSize = int.Parse(ConfigurationManager.AppSettings["MemberPostsPageSize"]);
    int totalPages = GetTotalPages(totalNumberOfPosts, pageSize);
    int currentPage = 1;

    if (Request.QueryString["page"] != null)
    {
        int.TryParse(Request.QueryString["page"], out currentPage);
        if (currentPage < 1 || currentPage > totalPages)
        {
            currentPage = 1;
        }
    }

    SetIntroVisibility(currentPage);
    SetLinks(currentPage, totalPages);
    SetPageNumberText(currentPage, totalPages);

    return posts.Skip((currentPage - 1) * pageSize).Take(pageSize);
}

private int GetTotalPages(int numberOfPosts, int pageSize)
{
    return numberOfPosts % pageSize == 0
                ? numberOfPosts / pageSize
                : numberOfPosts / pageSize + 1;
}

private void SetIntroVisibility(int currentPage)
{
    membersIntro.Visible = currentPage == 1;
}

private void SetLinks(int currentPage, int totalPages)
{
    linkPrevious.Visible = currentPage != 1;
    linkNext.Visible = currentPage != totalPages;

    linkPrevious.NavigateUrl = FormatPageLink(currentPage - 1);
    linkNext.NavigateUrl = FormatPageLink(currentPage + 1);
}

private string FormatPageLink(int pageNumber)
{
    return string.Format("{0}{1}{2}",
                            Request.CurrentExecutionFilePath,
                            "?page=",
                            pageNumber);
}

private void SetPageNumberText(int currentPage, int totalPages)
{
    lblNumRecords.Text = string.Format("&nbsp;&nbsp;Page {0} of {1}&nbsp;&nbsp;", currentPage, totalPages);
    if(totalPages == 1)
    {
        lblNumRecords.Visible = false;
    }
}
Michael
A: 

you can bind using an objectdatasource and implement paging very easily there! this way you can fully reuse the bindable controls logic.........

Tim Mahy
Any links please on how to do this with a repeater and an in-memory collection of objects?
Michael
repeater is to lowlevel and has no build-in support for paging, if you want paging out-of-the-box you will need to use a higher level control...
Tim Mahy
Such as?Something lightweight ideally.
Michael