Tag Archives: extending pagelist

EPiServer:PageList with ItemDataBound

In my last post I explained how you can extend your episerver:pagelist with your own templates (i.e. SelectedItemTemplate, AlternatingItemTemplate). In this post I will show you how to extend your PageList so you can use ItemDataBound. This is very useful if you want to use asp:controls in your templates and then populate them from code behind.

In this post I will start with the code from my last post and extend it further.

1. Creating PageListEventArgs
First of all we need to create our own EventArgs by extending EventArgs. In this case we need to access to the PageData that is bound to the Template, and we also need access to the Template which should be rendered. So this is the class we need:

public class PageListEventArgs : EventArgs
{
public PageData DataItem { get; set; }
public Control ControlItem { get; set; }
}

If you look at the RepeaterItemEventArgs, which is used by the asp:Repeater, you can get some ideas what else that can be useful in this EventArgs.

2. Creating PageListEventHandler
This is where we create our Eventhandler that will use the PageListEventArgs we just made. It’s just two lines of code:

[Serializable]
public delegate void PageListEventHandler (object sender, PageListEventArgs e);

3. Add PageListEvenHandler to the PageList
Ok, now that we have made an EventHandler we need to use it somehow. So, in the PageList we add the PageListEventHandler:

public event PageListEventHandler ItemDataBound;

By doing this, we can now add events to our PageList. We now need to make sure that the event is triggered when it should. So let’s jump into CreateChildControls, and find where the Item/SelectedItemTemplate is added. Right below the

ItemTemplate.InstantiateIn(control2);

we add

if (ItemDataBound != null)
{
PageListEventArgs args = new PageListEventArgs();
args.ControlItem = control2;
args.DataItem = pages[i];
ItemDataBound.Invoke(this, args);
}

When this is done, we have the option to add the ItemDataBound-event to our PageList!

This is how you do it:

<Antecknat:PageList ID="PageList1" PageLinkProperty="PageLink" OnItemDataBound="PageList1_ItemDataBound" runat="server">
<ItemTemplate>
<asp:Literal ID="Literal1" runat="server"></asp:Literal><br />
</ItemTemplate>
</Antecknat:PageList>

or from code behind:

PageList1.ItemDataBound += new Antecknat.Web.WebControls.PageListEventHandler(PageList1_ItemDataBound);

And to modify the controls in the current template:

protected void PageList1_ItemDataBound(object sender, <span>Antecknat.Web.WebControls</span>.PageListEventArgs e)
{

Literal l = e.Item.FindControl("Literal1") as Literal;
if(l!=null)
l.Text = e.DataItem.PageName;
}

EPiServer:PageList with SelectedItemTemplate

This is a quick guide how to extend EPiServer:PageList with a SelectedItemTemplate. This is a good start if you want to try to extend it with a SeparatorTemplate or something more spectacular.

1. Create a class
I.e. PageList.cs, a recommendation is to follow EPiServers namespace, so in this case I would create my class in Antecknat.Web.WebControls.
This class should inherit EPiServer.Web.WebControls.PageList

namespace Antecknat.Web.WebControls
{
public class PageList : EPiServer.Web.WebControls.PageList
{

2. Create the SelectedItemTemplate
This is done by the following code:

private ITemplate _selectedItemTemplate;
[TemplateContainer(typeof(PageTemplateContainer)), Browsable(false), PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate SelectedItemTemplate
{
get
{
return this._selectedItemTemplate;
}
set
{
this._selectedItemTemplate = value;
}
}

3. Modify CreateChildControls()
With Reflector (the best program ever made?) we can reuse the way controls are added to the regular PageList. We need to change the current method so that the SelectedItemTemplate is used when is supposed to.
In this case I want the current page, the parent page, the parents parents page and so on to count as selected. So we’ll make a PageReferenceCollection containing these pages.

// Find pages that should be marked as Selected
PageReferenceCollection prcActivePages = new PageReferenceCollection();
PageReference prCurrentLevel = CurrentPage.PageLink;
while (prCurrentLevel != null && prCurrentLevel != PageReference.EmptyReference)
{
prcActivePages.Add(prCurrentLevel);
prCurrentLevel = EPiServer.DataFactory.Instance.GetPage(prCurrentLevel).ParentLink;
}

And where the regular ItemTemplate is added, we change the code from:

ItemTemplate.InstantiateIn(control2);

to:

if (prcActivePages.Contains(pages[i].PageLink)) // Add to SelectedItemTemplate if in Selected collection
SelectedItemTemplate.InstantiateIn(control2);
else // Add to normal ItemTemplate
ItemTemplate.InstantiateIn(control2);

4. Change web.config
This is not a mandatory step, but if you always want to be able to use your fresh PageList from any aspx or ascx in the project, add teh following line in <system.web><pages><controls>

<add tagPrefix="Antecknat" namespace="Antecknat.Web.WebControls" assembly="Antecknat"/>

5. Use your PageList
Now you can use your PageList in your .aspx and .ascx files.
Just type

<Antecknat:PageList ID="PageList1" runat="server>
<HeaderTemplate><ul></HeaderTemplate>
<FooterTemplate></ul></FooterTemplate>
<ItemTemplate><li><%# Container.CurrentPage.PageName %></li>
<SelectedItemTemplate><li class="selected"><%# Container.CurrentPage.PageName %></li>
</Antecknat:PageList>

And then add a PageDataCollection from code behind and databind it.

Download sourcecode
PageList.zip