displaying a list of posts determined by category on one page

Topics: ASP.NET 2.0, Controls
Feb 17, 2009 at 11:31 PM
I was just wondering if it is possible to extract a number of posts by category and display them all on one page. Just like the default.aspx page but with a more ordered list.

e.g:

Display the latest 1 Post summaries from the category News
Display the latest 5 Posts summaries from the category Features


Coordinator
Feb 17, 2009 at 11:51 PM
Edited Feb 18, 2009 at 2:22 AM
It's possible.  Here's one way to do it ...

EDIT:  I deleted the code in this post because I added more stuff to the code and put the combined version in the next post ...
Coordinator
Feb 18, 2009 at 2:21 AM
Edited Feb 18, 2009 at 2:40 AM
For limiting the number of posts per category, I'd suggest doing this by adding a property in User controls\PostList.ascx.cs that you can pass to.  PostList.ascx.cs already has logic built into it to limit the number of posts it shows.

You would add this new property into User controls\PostList.ascx.cs

private int _OverrideDisplayCount;
public int OverrideDisplayCount
{
    get { return _OverrideDisplayCount; }
    set { _OverrideDisplayCount = value; }
}

Also in PostList.ascx.cs, there's this line:

int count = Math.Min(BlogSettings.Instance.PostsPerPage, visiblePosts.Count);

To make use of OverrideDisplayCount, that line above would become:

int count = OverrideDisplayCount > 0 ? OverrideDisplayCount : Math.Min(BlogSettings.Instance.PostsPerPage, visiblePosts.Count);

To avoid getting the "Next Page", "Previous Page" links, in PostList.ascx.cs, anywhere in BindPosts() add,

if (OverrideDisplayCount > 0)
{
    hlPrev.Visible = false;
    hlNext.Visible = false;
}

In default.aspx, add this placeholder control:

<asp:PlaceHolder ID="plcContent" runat="server"></asp:PlaceHolder>

Then in default.aspx.cs, you can pass in the 'OverrideDisplayCount' to PostList.ascx.cs.  The code below is from default.aspx.cs.  I added the part in bold and commented out the line beginning with "PostList1.Posts=".

else if (Request.QueryString.Count == 0 || !string.IsNullOrEmpty(Request.QueryString["page"]) || !string.IsNullOrEmpty(Request.QueryString["theme"]) || !string.IsNullOrEmpty(Request.QueryString["blog"]))
{
    foreach (Category c in Category.Categories)
    {
        if (c.Posts.Count > 0)
        {
            System.Web.UI.HtmlControls.HtmlGenericControl h2 = new System.Web.UI.HtmlControls.HtmlGenericControl("h2");
            h2.InnerHtml = c.Title;

            User_controls_PostList postList = (User_controls_PostList)LoadControl("~/User controls/PostList.ascx");
            postList.Posts = c.Posts.ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));

            switch (c.Title)
            {
                case "News":
                    postList.OverrideDisplayCount = 1;
                    break;
                case "Features":
                    postList.OverrideDisplayCount = 5;
                    break;
                default:
                    break;
            }

            plcContent.Controls.Add(h2);
            plcContent.Controls.Add(postList);
        }
    }
    
    // comment out line below
    //PostList1.Posts = Post.Posts.ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));
    if (!BlogSettings.Instance.UseBlogNameInPageTitles)
        Page.Title = BlogSettings.Instance.Name + " | ";

    if (!string.IsNullOrEmpty(BlogSettings.Instance.Description))
        Page.Title += Server.HtmlEncode(BlogSettings.Instance.Description);
}
Feb 18, 2009 at 3:05 AM
Edited Feb 18, 2009 at 4:14 AM
Thank you,

I have made the modifications to the PostList.ascx.cs file.

I am unable to get the main function working though, but have managed to list two separate categories using in default.aspx.cs :

Guid categoryId = new Guid("2f4720b5-5d40-49f7-990c-381dbd428881");
Guid categoryIdTwo = new Guid("84c78fdb-d07e-4f3c-ba0f-b93ec23ce8be");
           
PostList1.OverrideDisplayCount = 1;           
PostList1.Posts = Post.GetPostsByCategory(categoryId).ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));
           
PostList2.OverrideDisplayCount = 5;           
PostList2.Posts = Post.GetPostsByCategory(categoryIdTwo).ConvertAll(new Converter<Post, IPublishable>(delegate(Post p) { return p as IPublishable; }));


and adding in default.aspx

  <uc1:PostList ID="PostList1" runat="server" />
  <uc1:PostList ID="PostList2" runat="server" />

which is probably a more messy way of doing it.

The above code works, but displays the last page link after each post.

Coordinator
Feb 18, 2009 at 3:54 AM
What you did there works well.  The loop I had was outputting every category ... so two different goals/outcomes.

But, when you say "displays the last page link after each post" ... I'm not sure what you mean by "last page link" ?  Is that something that is theme specific?  I'm testing with the Standard theme ...
Feb 18, 2009 at 4:18 AM
Edited Feb 18, 2009 at 4:19 AM
I think that when the page gets to the maximum number of posts, it automatically inserts the Next Page and or Last Page Links, for navigation. So they wont show up unless you have the maximum post amount for the page.

In the PostList.ascx.cs i added the following (Changes in Bold)

        if (stop < 0 || stop + index > visiblePosts.Count)
        {
            hlPrev.Visible = false;
            hlNext.Visible = false;
            return;
        }

        if (OverrideDisplayCount > 0)
        {
            hlPrev.Visible = false;
            hlNext.Visible = false;
        }

The only issue now is that it is displaying two Next Page links still if you are on Page 2 or greater.

Almost there now though.

Thanks a lot for your help.
Coordinator
Feb 18, 2009 at 4:28 AM
Okay, the Next / Previous links.  Actually the exact same code you added to turn off hlPrev and hlNext was in my earlier message (but I added it after originally posting it) ... lol.

How are you getting to page 2, btw?  If you are setting Visible to false for both hlPrev and hlNext, where is the link that allows the person to see page 2?
Feb 18, 2009 at 4:44 AM
Ah yeah, i didn't see that there.

I am only getting to page 2 when going into a full category listing page anyway not from the default.aspx page, so maybe that problem of the two next page links was already there.


Coordinator
Feb 18, 2009 at 4:56 AM
Edited Feb 18, 2009 at 4:59 AM
Hmm, not sure ... Back on a regular installation of BE, if I start browsing the posts for a category, the initial url is /category/Blog.aspx (category is Blog).  Then I get a "<< Previous posts" link at the bottom to get to page 2.  Then when I'm on page 2 (the url is /category/Blog.aspx?page=2), on the bottom left I have a link for "<< Previous posts" (which goes to page 3), and on the bottom right I have a link for "Next posts >>" which goes to page 1.  So basically, I'm not seeing two "next page links".

EDIT: Actually, I now see the multiple "Next Page" links ... I'll see if I can find out why they're there ...
Coordinator
Feb 18, 2009 at 5:07 AM
Okay, figured it out.  Change default.aspx like this:

<uc1:PostList ID="PostList1" runat="server" />
<uc1:PostList ID="PostList2" runat="server" visible="false" />

Then in default.aspx.cs,

PostList2.Visible = true;

Guid categoryId = new Guid("2f4720b5-5d40-49f7-990c-381dbd428881");
Guid categoryIdTwo = new Guid("84c78fdb-d07e-4f3c-ba0f-b93ec23ce8be");

As you can probably tell, both PostList1 and PostList2 were being displayed when default.aspx was being used for the category listing.  In this case, PostList2 isn't needed and shouldn't be shown.  The extra "next page" link was coming from PostList2, which had no posts, but the next page link was still showing ...
Feb 18, 2009 at 5:12 AM
Very nice, working well now!

Thanks again.