A few weeks ago we received the following request from one of our partners:
We would like to create a table with icons in the headers of the columns.
It would be interesting to see a blog post showing some kind of custom dev similar to that.
I have seen the blog entry of adding new columns to a table, but those cells were text cells.
I suppose adding an inline image in a cell is a bit more complex.
We always enjoy a challenge, so we decided to try this out. Consider the before and after screenshots pictured below.
On the left, a product item group is shown that uses regular field labels for the table column headers. This item group was
created using the default PageBuilder 4 behavior. On the right, you can see an item group where the labels
for the column headers have been replaced with icons using a bit of custom code.

In order to achieve this effect, you can use an ItemGroupBuilder or a CatalogBuilder with a custom
RecordResolveAction. We hook our custom code into the action by overriding the
OnResolve(ResolveTarget<Table>) method. This way we can replace the column headers in the tables
right after they have been resolved with product data.
The full code for the custom RecordResolveAction is listed below. We assume that the images for the column
headers are stored in ADAM records and that we can find the record image for each label by doing a field value search (e.g.
the image record for the weight column has a field called "Label" with value "Weight"). Once we have loaded our image record,
we create an
image element for it. Finally we clear the text items in the cell's paragraph and add the image
element to it, yielding an inline (or anchored) image element.
| 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
38
39
40
41
42
43
44
|
using System.Linq;
using Adam.Core;
using Adam.Core.Records;
using Adam.Core.Search;
using Adam.DocMaker.Core;
using Adam.DocMaker.Core.Geometry;
using Adam.PageBuilder.Core.Resolve;
namespace CustomDev
{
public class CustomRecordResolveAction : RecordResolveAction
{
public CustomRecordResolveAction(Application application) : base(application)
{
}
protected override void OnResolve(ResolveTarget<Table> tableTarget)
{
base.OnResolve(tableTarget);
// Iterate over the cells in the table header row.
foreach (Cell cell in tableTarget.Item.Rows.First().Cells)
{
// Load the image that corresponds to the label in the column heading cell.
string label = cell.ToText().Trim();
Record imageRecord = new Record(App);
imageRecord.Load(new SearchExpression(string.Format("Label='{0}'", label)));
// Create a new image box to place in the cell.
Document document = tableTarget.Document;
RectangleD imageBox = new RectangleD(0, 0, 16, 16);
ImageElement imageElement = document.CreateImageElement(imageBox);
imageElement.ReplaceImage(ReplaceImageSource.Record, imageRecord.Id);
imageElement.ObjectStyle =
document.ObjectStyles.Single(style => style.Name == "Column Header");
// Clear the contents of the cell and put the image in it instead.
Paragraph paragraph = cell.Paragraphs.Single();
paragraph.Items.RemoveAll();
paragraph.Items.Add(imageElement);
}
}
}
}
|
Note that we also apply an object style to the image element. This is optional but can be used to apply certain effects, like
frame fitting options, transparency, etc. Any style you want to use here must first be defined in the design template document.
That's it for today. If you too have been following this blog series and you are struggling with something that
might make an interesting blog topic, please let us know. We always welcome all the feedback we can get.