Adding inline images to table cells

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.

Comments

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