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.