Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Item and Query String binding

Not Rated Yet

Along with the standard Part 1. Data binding and XPath selectors scryber has 2 more methods of binding to external data. The item binding and query-string binding.

 

Article Contents

 

Binding to the item collection

 

Whether you create your document in code, or with an pdfx template it always has an item collection associated with it MyDocument.Items. And this collection is simply a keyed object collection, that can be used to store anything required. It is unique to the document, and empty by default. However it can be used by components within the document to retrieve information based on the key.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:styles="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              >
  <Info>
    <Title>{item:Title}</Title>
  </Info>
  <Pages>
    <pdf:Page id="Rect2s" styles:margins="20pt" styles:font-family="Times" >
      <Content>
        <pdf:H1 text="{item:Title}" outline-title="{item:Title}"/>
        <pdf:H3 >Report dates from <pdf:Date value="{item:StartDate}" styles:date-format="dd MMM yyyy" />
        to <pdf:Date value="{item:EndDate}" styles:date-format="dd MMM yyyy" />
        </pdf:H3>
      </Content>
    </pdf:Page>
  </Pages>
</pdf:Document>

 

And in our document loading we need to add the code to set the Title, StartDate and EndDate items.

 

	doc = Scryber.Components.PDFDocument.ParseDocument(path);
	doc.Items["Title"] = "Annual Sales Figures";
	doc.Items["StartDate"] = new DateTime(2013, 04, 01);
	doc.Items["EndDate"] = new DateTime(2014, 03, 31);
	doc.ProcessDocument(outputstream, true);

 


 

As we can see, the items collection can be used for any type of object, but the type of object must match the type of the property it is being assigned to. Unlike XPath (or query string binding) the item binding is strongly typed. You cannot put a string object in the StartDate item because the property it is binding to is PDFDate.Value which requires a DateTime value. Setting it to a string will raise an argument exception - Object of type 'System.String' cannot be converted to type 'System.DateTime'.

If the item is not present in the collection then no value will be set, however this is not considered an error condition, and execution will continue as if the property had not been set.

Binding to the title element in the document info is only available in version 8.9+, previous to that release the document info was not bindable.

The advantage of using the item collection over finding the item and explicitly finding the component and setting the value is to decouple the structure of the document from the information you are presenting. In the above example, if we changed the layout and put the dates separately as start date and end date, then we don't have to change the code at all. We are not dependent on the id's or names of components.

 

Binding to styles

 

The binding of data is not limited to component values. Styles are also bindable, along with the style definitions (it even works in referenced files)

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:styles="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              >
  <Info>
    <Title>{item:Title}</Title>
  </Info>
  <Styles>
    <styles:Style applied-class="{item:classname}" >
      <styles:Fill color="{item:fillcolor}"/>
    </styles:Style>
  </Styles>
  <Pages>
    <pdf:Page id="Rect2s" styles:margins="20pt" styles:font-family="Times" >
      <Content>
        <pdf:H1 styles:fill-color="{item:fillcolor}" text="{item:Title}" outline-title="{item:Title}"/>
        <pdf:H3 styles:class="{item:classname}" >Report dates from <pdf:Date value="{item:StartDate}" styles:date-format="dd MMM yyyy" />
        to <pdf:Date value="{item:EndDate}" styles:date-format="dd MMM yyyy" />
        </pdf:H3>
      </Content>
    </pdf:Page>
  </Pages>
</pdf:Document>

 

    doc = Scryber.Components.PDFDocument.ParseDocument(path);
    doc.Items["Title"] = "Annual Sales Figures";
    doc.Items["StartDate"] = new DateTime(2013, 04, 01);
    doc.Items["EndDate"] = new DateTime(2014, 03, 31);
    doc.Items["classname"] = "blue";
    doc.Items["fillcolor"] = new Scryber.Drawing.PDFColor(0, 0, 1);
    doc.ProcessDocument(outputstream, true);

 


 

We can see in this example the fill color is assigned to the H1 component directly, for the H3 component we are dynamically setting the class name, and this is dynamically set on the style definition along with the inner fill color.

All style items and attributes are bindable

 

Complex item selectors

 

The item collection can contain any object or value type - a simple value such as a string or color is easy, but it could just as well be a complex class instance with inner properties and collections.

The {item:...} expression supports property selectors to any depth, along with collections that are indexed either by key or position. It does not support method calls or invocations.

	{item:selector.property[index].innerproperty}  // valid
	{item:selector['key'].innerproperty}           // valid
	
	{item:selector.getColor()}                     // invalid

Knowing this we can improve the example by creating a custom class to hold our style information

 

    public class ReportInfo
    {
        public string Title { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }

    public class Theme
    {
        public Dictionary&lt;string, ThemeItem&gt; Items { get; set; }

        public Theme()
        {
            this.Items = new Dictionary&lt;string, ThemeItem&gt;();
        }
    }

    public class ThemeItem
    {
        public string Name { get; set; }
        public Scryber.Drawing.PDFColor FillColor { get; set; }
        public Scryber.Drawing.PDFColor BorderColor { get; set; }
        public Scryber.Drawing.PDFUnit BorderWidth { get; set; }
    }

 

And then we can use these classes to populate a couple of instances and assign to the items collection when generating the document.

 

	Theme theme = new Theme();
    theme.Items.Add("heading", new ThemeItem()
    {
        Name = "heading-blue",
        BorderColor = new Drawing.PDFColor(0, 1, 0),
        BorderWidth = 1,
        FillColor = new Drawing.PDFColor(0, 0, 1)
    });

    theme.Items.Add("subhead", new ThemeItem()
    {
        Name = "subhead-gray",
        BorderWidth = 0,
        FillColor = new Drawing.PDFColor(0.3, 0.3, 0.3)
    });

    ReportInfo info = new ReportInfo()
    {
        Title = "Annual Sales Figures",
        StartDate = new DateTime(2013, 04, 01),
        EndDate = new DateTime(2014, 03, 31)
    };

    doc = Scryber.Components.PDFDocument.ParseDocument(path);
    doc.Items["Info"] = info;
    doc.Items["Theme"] = theme;
    doc.ProcessDocument(outputstream, true);

 

And then we can use these classes to populate a couple of instances and assign to the items collection when generating the document.

 

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:styles="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              >
  <Info>
    <Title>{item:Info.Title}</Title>
  </Info>
  <Styles>
    <styles:Style applied-class="{item:Theme.Items['heading'].Name}" >
      <styles:Fill color="{item:Theme.Items['heading'].FillColor}"/>
      <styles:Border color="{item:Theme.Items['heading'].BorderColor}" width="{item:Theme.Items['heading'].BorderWidth}"/>
    </styles:Style>

    <styles:Style applied-class="{item:Theme.Items['subhead'].Name}" >
      <styles:Fill color="{item:Theme.Items['subhead'].FillColor}"/>
      <styles:Border color="{item:Theme.Items['subhead'].BorderColor}" width="{item:Theme.Items['subhead'].BorderWidth}"/>
    </styles:Style>
  </Styles>
  <Pages>
    <pdf:Page id="Rect2s" styles:margins="20pt" styles:font-family="Times" >
      <Content>
        <pdf:H1 styles:class="{item:Theme.Items['heading'].Name}" 
                text="{item:Info.Title}" outline-title="{item:Info.Title}"/>

        <pdf:H3 styles:class="{item:Theme.Items['subhead'].Name}" >
          Report dates from <pdf:Date value="{item:Info.StartDate}" styles:date-format="dd MMM yyyy" />
          to <pdf:Date value="{item:Info.EndDate}" styles:date-format="dd MMM yyyy" />
        </pdf:H3>
      </Content>
    </pdf:Page>
  </Pages>
</pdf:Document>

 


 

Obviously the way you structure the classes and how they are bound is entirely dependent on what information is needed, and where it comes from, but it is flexible enough to drive a lot of dynamic content.

 

XPath navigators in the item collection

 

As demonstrated in Part 5. Assigning dynamic data, the items collection can take an XPathNavigable instance and can be used as the current data context for further binding operations.

We stick to the XPath binding mechanism as it allows complex expressions, calculations and loose typing. Whilst there may be extra overhead in converting an object to XPath, it is more flexible in the long run.

 

Query string binding

 

Along with the {item:...} binding expression, scryber also supports the {qs:...} expression. Purely for web applications, this will take a single string key as the name of the parameter on the url, and push into the required property.

Query string binding happens at load time not data-binding time, as it does not change overtime and can be used with binding on data sources. e.g. Paging results, but can be used anywhere an XPath or Item binding expression is supported.

<data:ForEach datasource-id="MyXMLData" select="Children" start-index="{qs:start}" count="{qs:pagesize}" >
    <Template>

    </Template>
</data:ForEach>

http://mysite.com/GetReportPage.pdfx?start=1000&pagesize=1000

So this request would only output up to 1000 Children items starting at the 1000th item.

 

Query string and item parameters

 

As shown in Part 4. Transform Parameters the XMLDataSource supports specific use of item and query-string parameters to alter transformations, to change the final output.



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  No Ratings Yet   
Number of Ratings : 0
  Comments
Add Comment
No Comments Yet