Adding variable page headers to your automated catalog

When building an automated catalog using PageBuilder 4, you can specify a custom provider engine that extends or changes the default behavior. In today's blog post we take a look at a concrete example.

Suppose you want to add running headers to your catalog, giving summarized information about the products on each page (not unlike the page headers found in phone books or dictionaries).

We can accomplish this by implementing a custom CatalogBuilder, which inherits all default functionality from its base class, but also adds the functionality of adding page headers in a custom PagePaginateAction:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
using Adam.Core;
using Adam.PageBuilder.Core.Build;

namespace PageHeaderEngine
{
 class PageHeaderCatalogBuilder : CatalogBuilder
 {
  public PageHeaderCatalogBuilder(Application application) : base(application)
  {
   PagePaginateAction = new PageHeaderPaginateAction(application);
  }
 }
}

The most sensible time to add our header to each page is when all products have been added to that page, right before the next page is added to the catalog. This means we want to override the OnPaginatedPage method of the PagePaginateAction:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
using System;
using System.Collections.Generic;
using System.Linq;
using Adam.Core;
using Adam.Core.Records;
using Adam.PageBuilder.Core.Extensions;
using Adam.PageBuilder.Core.Paginate;

namespace PageHeaderEngine
{
 class PageHeaderPaginateAction : PagePaginateAction
 {
  public PageHeaderPaginateAction(Application application) : base(application)
  {
  }

  protected override void OnPaginatedPage(PageTarget pageTarget)
  {
   IEnumerable<Guid> recordIds = pageTarget.GroupsOnPage
    .Select(group => group.GetResolvedRecordId())
    .Where(id => id.HasValue)
    .Select(id => id.Value);

   RecordCollection recordCollection = new RecordCollection(App);
   recordCollection.Load(recordIds.ToList());
   IEnumerable<string> productIds = recordCollection.Cast<Record>()
    .Select(record => record.Fields["ProductID"].MyLanguage.ToString());

   if (productIds.Any())
   {
    string pageHeader = 
     string.Format("{0}-{1}", productIds.First(), productIds.Last());
    AddHeaderBox(pageTarget.Page, pageHeader);
   }
  }
 }
}

The PageTarget that is passed to the OnPaginatedPage method contains a list with all item groups that have been placed on the page. For each item group, we can obtain the id of the record that has been used to build the item group (using the GetResolvedRecordId extension method).

Next we load the relevant records and collect the corresponding product identifiers. Of course you could use any other record field at this point, depending on what information you want to show in the page header. In the example above, the page header string contains the id of the first and the last product on the page, separated by a hyphen.

Finally, in the AddHeaderBox helper method, we use the DocMaker API to add a formatted run containing our page header string to a new text box in the top left corner of the current page:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private static void AddHeaderBox(Page page, string pageHeader)
{
 Document document = page.OwnerDocument;

 RectangleD bounds = new RectangleD(page.Bounds.Location, new SizeD(120, 20));
 TextElement headerBox = document.CreateTextElement(bounds.Offset(40, 40));
 page.OwnerSpread.Elements.Add(headerBox);

 Paragraph paragraph = document.CreateParagraph();
 headerBox.Story.Paragraphs.Add(paragraph);

 Run run = document.CreateRun();
 run.Value = pageHeader;
 run.Formatting.FontFamily = "Calibri";
 run.Formatting.FontSize = 14;
 run.Formatting.FontColor = new FontColor(65, 173, 73);
 paragraph.Items.Add(run);
}

That is all the code we are going to write today. We now need to compile our class library into an assembly which we can register in the GAC or in the ADAM database (how to do this is explained in detail in the ADAM Developer Guide). Next we add our custom provider to the PageBuilder build catalog engines setting:

XML
1
2
3
4
5
6
<engines>
  <add name="Default" 
    type="Adam.PageBuilder.Core.Build.CatalogBuilder, Adam.PageBuilder.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=3266306e8df4a2d3" />
  <add name="PageHeaderEngine" 
    type="PageHeaderEngine.PageHeaderCatalogBuilder, PageHeaderEngine" />
</engines>

Now we can select our PageHeaderEngine when building a catalog in PageBuilder Studio. The resulting catalog will look the same as before, but each page will contain a header with the identifiers of the first and the last product paginated on that page, making it easy for customers to locate a product based on its product id (assuming you choose to sort the products in the catalog by product id).

The usual warning applies that the above code is meant for illustrative purposes and should not be used directly in a production environment. At the very least you should check for error conditions to make the code less vulnerable.

Comments

Leave a comment
You must be logged in to post comments.
Sign in now
 
 
Technical
Business
rss feed