TX Text Control provides a ready-to-use Ribbon bar with fully functional ribbon tabs for various tasks including the RibbonReportingTab TX Text Control .NET for Windows Forms
Windows.Forms.Ribbon Namespace
RibbonReportingTab Class
The RibbonReportingTab class represents a Windows Forms ribbon tab to integrate mail merge and reporting functionality.
to include reporting features.

The RibbonReportingTab can be connected to a DataSourceManager TX Text Control .NET for Windows Forms
DocumentServer.DataSources Namespace
DataSourceManager Class
The DataSourceManager class is designed for handling all existing kinds of data sources which can be used together with the MailMerge class.
object that encapsulates the complete handling, logic and ready-to-use dialog boxes for the reporting template creation task.

When loading a data source into the DataSourceManager, the data structure is used to fill the Insert Merge Field drop-down lists. Consider the following simple JSON data object:

[
{
"Id": 1,
"Customer": {
"Id": 1,
"Name": "Text Control, LLC",
"Street": "6926 Shannon-Willow Rd",
"ZipCode": "28226",
"City": "Charlotte",
"Country": "United States",
"Contacts": [
{
"Id": 1,
"Name": "Paul De Wright"
}
]
}
}
]
view raw data.json hosted with ❤ by GitHub

When loaded using the DataSourceManager, the drop-down list displays the data column names:

Unmasked data

Even if the data column names in this example are not really cryptic, real-world database structures and naming can be complex and confusing for end-users. This concept shows how to change the drop-down item display text for merge fields to provide end-users additional information.

The first data row of the data source is used to change the drop-down items with user-friendly strings. The following data source is used in this example:

[
{
"Id": "The Id [Id]",
"Customer": {
"Id": "Customer Id [Customer/Id]",
"Name": "Customer Name [Customer/Name]",
"Street": "Customer Street [Customer/Street]",
"ZipCode": "Customer Zip Code [Customer/ZipCode]",
"City": "Customer City [Customer/City]",
"Country": "Customer Country [Customer/Country]",
"Contacts": [
{
"Id": "Customer Contacts Id [Customer/Contacts/Id]",
"Name": "Customer Contacts Name [Customer/Contacts/Name]"
}
]
}
},
{
"Id": 1,
"Customer": {
"Id": 1,
"Name": "Text Control, LLC",
"Street": "6926 Shannon-Willow Rd",
"ZipCode": "28226",
"City": "Charlotte",
"Country": "United States",
"Contacts": [
{
"Id": 1,
"Name": "Paul De Wright"
}
]
}
}
]
view raw test.json hosted with ❤ by GitHub

When changing the strings after the data has been loaded into the DataSourceManager, the drop-down items show user-friendly strings instead of the actual data column names.

dynamic joData = null;
private void Form1_Load(object sender, EventArgs e)
{
joData = JsonConvert.DeserializeObject(File.ReadAllText("data.json"));
ribbonReportingTab1.DataSourceManager.LoadJson(joData.ToString());
ribbonReportingTab1.DataSourceManager.PossibleMergeFieldColumnsChanged +=
DataSourceManager_PossibleMergeFieldColumnsChanged;
MaskDataColumnNames(joData);
}
private void DataSourceManager_PossibleMergeFieldColumnsChanged(object sender, EventArgs e)
{
MaskDataColumnNames(joData);
}
view raw code.cs hosted with ❤ by GitHub

When clicking on a merge field drop-down item, a valid field is inserted with the actual name and not the masked user-friendly string.

Masked data

The following function can be called after data has been loaded into the DataSourceManager. It finds the Insert Merge Field drop-down button, gets the currently selected master table that is automatically returned by the DataSourceManager and calls the ApplyMaskedString method:

private void MaskDataColumnNames(dynamic data)
{
// flatten data object in case of an array
if (data.GetType() == typeof(JArray))
data = data[0];
// find merge fields ribbon menu button
RibbonMenuButton ctlInsertMergeFields =
ribbonReportingTab1.FindItem(
RibbonReportingTab.RibbonItem.TXITEM_InsertMergeField)
as RibbonMenuButton;
// get the selected master table info
DataTableInfo dataTableInfo =
ribbonReportingTab1.DataSourceManager.MasterDataTableInfo;
// select token in data object
if (dataTableInfo.TableName != "RootTable")
{
data = data.SelectToken("$.." + dataTableInfo.TableName);
}
// change the strings
ApplyMaskedString(ctlInsertMergeFields.DropDownItems, data);
}
view raw code.cs hosted with ❤ by GitHub

The ApplyMaskedString function loops through all merge field drop-down items in order to replace the text property with the first associated data from the first data row in the data source. In case of a child table, the ApplyMaskedString function is called recursively.

private void ApplyMaskedString(RibbonItemCollection ribbonItems, dynamic data)
{
// flatten data object in case of an array
if (data.GetType() == typeof(JArray))
data = data[0];
// loop through all ribbon items in the "insert merge fields" menu
foreach (Control ribbonButton in ribbonItems)
{
// in case, the item is a drop-down, call ApplyMaskedString
// recursively with a new data object
if (ribbonButton is RibbonMenuButton)
{
ApplyMaskedString(
((RibbonMenuButton)ribbonButton).DropDownItems,
data[ribbonButton.Text]);
}
// in case it is a merge field insert button
else if (ribbonButton is RibbonButton)
{
// and it is not a separator or title
if (!ribbonButton.Name.StartsWith("TXITEM_"))
{
// get the data from the first data row
var dataValue = data[ribbonButton.Text];
if (dataValue == null)
continue;
if (dataValue.GetType() == typeof(JValue))
{
// change the actual text
ribbonButton.Text = dataValue.Value;
}
}
}
}
}
view raw code.cs hosted with ❤ by GitHub

Try this on your own and download the sample from our GitHub repository.