Version X14 comes with pre-configured ribbon tabs for all typical tasks of TX Text Control. One of these ribbon tabs is the RibbonReportingTab. It provides a fully featured ribbon tab to create MS Word compatible templates for the Text Control Reporting Framework. Data sources such as MS SQL, ODBC and ADO.NET can be loaded, the master table can be set and available merge blocks and merge fields can be inserted.

Build your own template designer with the new DataSourceManager class

This new ribbon tab is based on the new public class DataSourceManager that encapsulates the complete handling, logic and ready-to-use dialog boxes for the reporting template creation task. The following diagram shows the new classes in detail:

DataSourceManager class

Essentially, the DataSourceManager provides all information required to create a fully-featured template designer. Like with MailMerge, a data source can be loaded from a DataSet, DataTable, Json, an object or XML. In this sample, a simple .NET class is used as a data source:

public class Order
{
public int OrderID { get; set; }
public Customer Customer { get; set; }
public List<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public Product Product { get; set; }
public int Quantity { get; set; }
}
public class Product
{
public string Name { get; set; }
}
public class Customer
{
public string Name { get; set; }
}
view raw test.cs hosted with ❤ by GitHub

This sample shows the typical work-flow of a template designer:

DataSourceManager class

After clicking the button Load Data Source, a new instance of the DataSourceManager is created and the data object is loaded.

// create new merge data
Order order = new Order()
{
OrderID = 123,
Customer = new Customer()
{
Name = "Peter Welch"
},
OrderItems = new List<OrderItem>()
{
new OrderItem() {
Product = new Product() {
Name = "Product A" },
Quantity = 2 }
}
};
// create a new instance of the DataSourceManager
dsManager = new DataSourceManager();
// load the data source
dsManager.LoadSingleObject(order);
view raw test.cs hosted with ❤ by GitHub

When a data source is loaded into the DataSourceManager, a ComboBox is bound to all available DataTables. Additionally, the events PossibleMergeFieldColumnsChanged and PossibleMergeBlockTablesChanged are attached to update two other ComboBoxes that list the available merge fields and merge blocks.

// attach events to monitor available merge fields and merge blocks
dsManager.PossibleMergeFieldColumnsChanged +=
DsManager_PossibleMergeFieldColumnsChanged;
dsManager.PossibleMergeBlockTablesChanged +=
DsManager_PossibleMergeBlockTablesChanged;
// attach the available tables to the combobox
cbMasterTable.DataSource =
dsManager.DataTables.ToList<DataTableInfo>();
cbMasterTable.DisplayMember = "TableName";
view raw test.cs hosted with ❤ by GitHub

When the internal master table is changed, the ComboBoxes are updated with the available fields and blocks:

private void DsManager_PossibleMergeBlockTablesChanged(object sender, EventArgs e)
{
// attach the available merge blocks to the combobox
cbMergeBlocks.Text = "";
cbMergeBlocks.DataSource =
dsManager.PossibleMergeBlockTables.ToList<DataTableInfo>();
cbMergeBlocks.DisplayMember = "TableName";
}
private void DsManager_PossibleMergeFieldColumnsChanged(object sender, EventArgs e)
{
// attach the available merge fields to the combobox
cbMergeFields.Text = "";
cbMergeFields.DataSource =
dsManager.PossibleMergeFieldColumns.ToList<DataColumnInfo>();
cbMergeFields.DisplayMember = "ColumnName";
}
view raw test.cs hosted with ❤ by GitHub

If the input position is inside a merge block, only the available fields and blocks inside this block should be available. Therefore, the SubTextPartEntered event is used to define a new internal master table. The ComboBoxes are updated automatically through the attached events.

private void textControl1_SubTextPartEntered(object sender,
TXTextControl.SubTextPartEventArgs e)
{
// is the SubTextPart a valid merge block?
if (DataSourceManager.IsMergeBlock(e.SubTextPart))
{
// set the merge block as the new internal master table
if(dsManager.DataTables.Contains(e.SubTextPart.Name.Remove(0, 5)))
dsManager.MasterDataTableInfo =
dsManager.DataTables[e.SubTextPart.Name.Remove(0,5)];
}
}
private void textControl1_SubTextPartLeft(object sender,
TXTextControl.SubTextPartEventArgs e)
{
// set the master table back to the originally selected table
dsManager.MasterDataTableInfo = cbMasterTable.SelectedItem as DataTableInfo;
}
view raw test.cs hosted with ❤ by GitHub

When clicking the Preview button, the new Merge method of the DataSourceManager is used to merge the data into the template:

private void cbPreview_CheckedChanged(object sender, EventArgs e)
{
// preview the mail merge document
if (cbPreview.Checked)
{
// save the template
gbMergeElements.Enabled = false;
textControl1.EditMode = TXTextControl.EditMode.ReadAndSelect;
textControl1.Save(out previewTemplate,
TXTextControl.BinaryStreamType.InternalUnicodeFormat);
// merge the template using the DataSourceManager
IList<byte[]> documents =
dsManager.Merge(previewTemplate, textControl1);
// load the merged document into TextControl
textControl1.Load(documents[0],
TXTextControl.BinaryStreamType.InternalUnicodeFormat);
}
else
{
// load back the stored template
gbMergeElements.Enabled = true;
textControl1.EditMode = TXTextControl.EditMode.Edit;
textControl1.Load(previewTemplate,
TXTextControl.BinaryStreamType.InternalUnicodeFormat);
}
}
view raw test.cs hosted with ❤ by GitHub

Using the DataSourceManager, the complete task of designing mail merge templates can be realized. The class encapsulates the work-flow, logic and all required dialog boxes and preview functionality.

Stay tuned for more details about X14!