TX Text Control provides a ready-to-use Ribbon bar with fully functional ribbon tabs for various tasks including the RibbonReportingTab to include reporting features. The RibbonReportingTab can be connected to a DataSourceManager 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" } ] } } ] When loaded using the DataSourceManager, the drop-down list displays the data column names: 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" } ] } } ] 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); } 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. 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); } 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; } } } } } Try this on your own and download the sample from our GitHub repository.