Sorting Links in Pages Widget

Topics: Controls
Apr 23, 2009 at 9:45 PM
Is there anyway to sort the links in the pages widget? If not, can that be a new feature on the next build? Reason I ask is because now that sorting is enabled in the blogroll widget, it would be cool if we could sort the pages links, too. :)
Jul 9, 2009 at 8:38 PM
Edited Jul 9, 2009 at 8:39 PM

Code tested on Blogengine 1.5 final only !

Hi there,

I thought of a quick and easy way to implement sorting on the pages widget (or control) by using the Page.DateCreated property.

This property can be found back in the App_Data/pages xml-files that contain your page's data. Everytime you add a new page the creationdate is added.

If needed you can manipulate this field in the xml-file after creation in order to change the order of the pages listed in the control (or widget).

To set this up all you need to do is change the BindPages() method which you can find in the App_Code/Controls/PageList.cs class.

Here it is:

using System.Data;

private HtmlGenericControl BindPages()
    {
        
        //create datatable for sorting

        DataTable dt = new DataTable();
        dt.Columns.Add("DateCreated", typeof(System.DateTime));
        dt.Columns.Add("Description", typeof(System.String));
        dt.Columns.Add("Title", typeof(System.String));
        dt.Columns.Add("RelativeLink", typeof(System.String));

        DataRow dr;

        foreach (BlogEngine.Core.Page page in BlogEngine.Core.Page.Pages)
        {
            if (page.ShowInList && page.IsPublished)
            {

                //add page data to datatable
                dr = dt.NewRow();
                dr["DateCreated"] = page.DateCreated;
                dr["Description"] = page.Description.ToString();
                dr["Title"] = page.Title.ToString();
                dr["RelativeLink"] = page.RelativeLink.ToString();
                dt.Rows.Add(dr);
            }
        }

        //create html control
        HtmlGenericControl ul = new HtmlGenericControl("ul");
        ul.Attributes.Add("class", "pagelist");
        ul.ID = "pagelist";

        //loop through datatable to fill the ul with sorted listitems

        foreach (DataRow row in dt.Select("","DateCreated ASC"))
        {

            HtmlGenericControl li = new HtmlGenericControl("li");

            HtmlAnchor anc = new HtmlAnchor();
            anc.HRef = row["RelativeLink"].ToString();
            anc.InnerHtml = row["Title"].ToString();
            anc.Title = row["Description"].ToString();

            li.Controls.Add(anc);
            ul.Controls.Add(li);
        }


        return ul;
    }

 

Hope this can help out some of you!

cheers,

KGB

Sep 29, 2010 at 4:20 PM
Edited Sep 29, 2010 at 4:23 PM

If you're using PageMenu from http://rtur.net/blog/page/CSS-Page-Menu.aspx

you can sort by creation date with this little tweak of PageMenu.cs (my modifications are bolded):

 

using System;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Collections.Generic;
using BlogEngine.Core;

namespace Controls
{
    public class PageMenu : Control
    {
        static PageMenu()
        {
            BlogEngine.Core.Page.Saved += delegate { _Html = null; };
        }

        #region Properties

        private static object _SyncRoot = new object();
        private static string _Html;
        private bool _ulIdSet = false;
        string _curPage = HttpUtility.UrlEncode(GetPageName(HttpContext.Current.Request.RawUrl.ToLower()));

        private string Html
        {
            get
            {
                lock (_SyncRoot)
                {
                    HtmlGenericControl ul = BindPages();
                    System.IO.StringWriter sw = new System.IO.StringWriter();
                    ul.RenderControl(new HtmlTextWriter(sw));
                    _Html = sw.ToString();
                }

                return _Html;
            }
        }

        #endregion

        private HtmlGenericControl BindPages()
        {
            // recursivly get all children of the root page
            HtmlGenericControl ul = GetChildren(Guid.Empty);

            AddMenuItem(ul, Resources.labels.contact, "~/contact.aspx");

            return ul;
        }

        bool HasChildren(Guid pageId)
        {
            bool returnValue = false;

            foreach (BlogEngine.Core.Page page in BlogEngine.Core.Page.Pages)
            {
                if (page.ShowInList && page.IsPublished)
                {
                    if (page.Parent == pageId)
                    {
                        returnValue = true;
                        break;
                    }
                }
            }

            return returnValue;
        }

        HtmlGenericControl GetChildren(Guid parentId)
        {
            HtmlGenericControl ul = new HtmlGenericControl("ul");

            if (!_ulIdSet)
            {
                ul.Attributes.Add("id", "navmenu");
                _ulIdSet = true;

                AddMenuItem(ul, Resources.labels.home, "~/default.aspx");
               AddMenuItem(ul, Resources.labels.archive, "~/archive.aspx");
            }

            List<BlogEngine.Core.Page> pages = new List<BlogEngine.Core.Page>();

            foreach (BlogEngine.Core.Page page in BlogEngine.Core.Page.Pages)
            {
                if (page.ShowInList && page.IsPublished)
                {
                    if (page.Parent == parentId)
                    {
                        pages.Add(page);
                    }
                }
            }

            pages.Sort(CompareCreationDates);

            foreach (BlogEngine.Core.Page page in pages)
            {
                HtmlGenericControl li = new HtmlGenericControl("li");
                string pageName = HttpUtility.UrlEncode(GetPageName(page.RelativeLink.ToString().ToLower()));

                HtmlAnchor anc = new HtmlAnchor();
                anc.HRef = page.RelativeLink.ToString();
                anc.InnerHtml = "<span>" + page.Title + "</span>";
                anc.Title = page.Description;

                if (pageName == _curPage)
                {
                    anc.Attributes.Add("class", "current");
                }

                li.Controls.Add(anc);

                if (HasChildren(page.Id))
                {
                    HtmlGenericControl subUl = GetChildren(page.Id);
                    li.Controls.Add(subUl);
                }
                ul.Controls.Add(li);
            }

            return ul;
        }

        private void AddMenuItem(HtmlGenericControl ul, string pageName, string pageUrl)
        {
            HtmlGenericControl li = new HtmlGenericControl("li");
            HtmlAnchor anc = new HtmlAnchor();

            anc.HRef = pageUrl;
            anc.InnerHtml = "<span>" + pageName + "</span>";
            anc.Title = pageName;

            if (GetPageName(pageUrl).ToLower() == _curPage.ToLower())
            {
                anc.Attributes.Add("class", "current");
            }

            li.Controls.Add(anc);
            ul.Controls.Add(li);
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            writer.Write(Html);
            writer.Write(Environment.NewLine);
        }

        public static string GetPageName(string requestPath)
        {
            if (requestPath.IndexOf('?') != -1)
                requestPath = requestPath.Substring(0, requestPath.IndexOf('?'));
            return requestPath.Remove(0, requestPath.LastIndexOf("/") + 1).ToLower();
        }

        //Pages created first are placed first/at the top
        private static int CompareCreationDates(BlogEngine.Core.Page a, BlogEngine.Core.Page b)
        {
            return a.DateCreated > b.DateCreated ? 1 : -1;
        }
    }
}

 

- agibsen