Posted in: Comments

If you add an EPiServer Property control to the PageLists ItemTemplate it handles CurrentPage as expected, you can also get the CurrentPage by the binding expression:

<%# Container.CurrentPage %>

Lets say you have an user control (.ascx) in the ItemTemplate instead, then the CurrentPage will be the actual page the PageList control is added to. We can workaround this by having a property in our user control and set it to Container.CurrentPage.PageLink and set each Property’s PageLink to it, but let’s make it a little bit more sophisticated.

CurrentPage is resolved by implementing IPageSource or ICurrentPage. But how do we implement them?

IPageSource has one property and two methods which needs to be implemented.

PageData CurrentPage { get; } 
PageDataCollection GetChildren(PageReference pageLink); 
PageData GetPage(PageReference pageLink);

One way is to implement IPageControl that has the property PageSource which is of the type IPageSource. Then can we use that property when implementing the IPageSource methods and properties.

In our case we need to find the nearest control that implements IPageSource itself.

public IPageSource PageSource
{
    get
    {
        if (this._pageSource == null)
        {
            this._pageSource = this.NamingContainer as IPageSource;

            if (this._pageSource == null)
            {
                this._pageSource = this.Page as IPageSource;
            }

            if (this._pageSource == null)
            {
                this._pageSource = DataFactory.Instance;
            }
        }

        return this._pageSource;
    }
    set
    {
        this._pageSource = value;
    }
}

In this case we’re looking at the NamingContainer, we could also traverse the control tree even further.

Now can we implement our CurrentPage.

public PageData CurrentPage
{
    get
    {
        return this.PageSource.CurrentPage;
    }
}

This is essentially what we need, but let’s implement all methods and properties. EPiServers default base class for user controls also have some other useful methods, so let’s add them too. This is the complete code:

namespace DV
{
    using System.Web.UI;
    using EPiServer;
    using EPiServer.Core;
    using EPiServer.Web.WebControls;

    public class UserControlContainer : UserControl, IPageControl, IPageSource
    {
        #region Member variables

        private IPageSource _pageSource;

        private PageReference _pageLink;

        private PageBase _page;

        #endregion

        #region IPageControl Members

        public PageReference PageLink
        {
            get
            {
                if (!string.IsNullOrEmpty(this.PageLinkProperty) && PageReference.IsNullOrEmpty(this._pageLink))
                {
                    PageReference reference;

                    if (this.CurrentPage.Property.TryGetValue<PageReference>(this.PageLinkProperty, out reference))
                    {
                        this._pageLink = reference;
                    }
                    else
                    {
                        this._pageLink = PageReference.EmptyReference;
                    }
                }

                return this._pageLink;
            }
            set
            {
                this._pageLink = value;
            }
        }

        public string PageLinkProperty { get; set; }

        public IPageSource PageSource
        {
            get
            {
                if (this._pageSource == null)
                {
                    this._pageSource = this.NamingContainer as IPageSource;

                    if (this._pageSource == null)
                    {
                        this._pageSource = this.Page as IPageSource;
                    }

                    if (this._pageSource == null)
                    {
                        this._pageSource = DataFactory.Instance;
                    }
                }

                return this._pageSource;
            }
            set
            {
                this._pageSource = value;
            }
        }

        #endregion

        #region IPageSource Members

        public PageData CurrentPage
        {
            get
            {
                return this.PageSource.CurrentPage;
            }
        }

        public PageDataCollection GetChildren(PageReference pageLink)
        {
            return this.PageSource.GetChildren(pageLink);
        }

        public PageData GetPage(PageReference pageLink)
        {
            return this.PageSource.GetPage(pageLink);
        }

        #endregion

        public UserControlContainer()
        {
        }

        public PageBase PageBase
        {
            get
            {
                if (this._page == null)
                {
                    this._page = this.Page as PageBase;

                    if (this._page != null)
                    {
                        return this._page;
                    }

                    this._page = this.Context.Handler as PageBase;

                    if (this._page == null)
                    {
                        throw new EPiServerException("This user control must be placed on an ASPX-page that inherits from EPiServer.PageBase");
                    }
                }

                return this._page;
            }
        }

        public PageData ContainerPage
        {
            get
            {
                return this.PageBase.CurrentPage;
            }
        }

        public bool IsValue(string propertyName)
        {
            return this.CurrentPage[propertyName] != null;
        }

        public string Translate(string key)
        {
            return this.PageBase.Translate(key);
        }

        public string TranslateForScript(string key)
        {
            return this.PageBase.TranslateForScript(key);
        }
    }
}

Now can we add a user control to a PageList:

<NetR:PageList AutoBind="true" PageLink="3" runat="server">
	<ItemTemplate>
		<units:Example runat="server" />
	</ItemTemplate>
</NetR:PageList>

And in our user control we can add Property controls as usual without needing to set each controls PageLink property:

<%@ Control Language="C#" CodeBehind="Example.ascx.cs" Inherits="DV.Templates.Units.Example" %>

<EPiServer:Property PropertyName="PageName" runat="server" />
<EPiServer:Property PropertyName="MainBody" runat="server" />

Please comment! Have you solved this problem in another way?