# Windows Forms Ribbon: Displaying User-Friendly Merge Field Names

> Database column names can be complex and confusing to end-users. This article shows how to display user-friendly names in the ribbon.

- **Author:** Bjoern Meyer
- **Published:** 2020-01-14
- **Modified:** 2026-07-17
- **Description:** Database column names can be complex and confusing to end-users. This article shows how to display user-friendly names in the ribbon.
- **4 min read** (659 words)
- **Tags:**
  - Mail Merge
  - Ribbon
  - Windows Forms
- **Web URL:** https://www.textcontrol.com/blog/2020/01/14/displaying-user-friendly-merge-field-names-in-the-ribbon/
- **LLMs URL:** https://www.textcontrol.com/blog/2020/01/14/displaying-user-friendly-merge-field-names-in-the-ribbon/llms.txt
- **LLMs-Full URL:** https://www.textcontrol.com/blog/2020/01/14/displaying-user-friendly-merge-field-names-in-the-ribbon/llms-full.txt
- **GitHub Repository:** https://github.com/TextControl/TextControl.WindowsForms.CustomRibbon

---

TX Text Control provides a ready-to-use Ribbon bar with fully functional ribbon tabs for various tasks including the RibbonReportingTabto include reporting features.

The *RibbonReportingTab* can be connected to a DataSourceManagerobject 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:

![Unmasked data](https://s1-www.textcontrol.com/assets/dist/blog/2020/01/14/a/assets/unmasked.webp "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"
        }
      ]
    }
  }
]
```

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.

![Masked data](https://s1-www.textcontrol.com/assets/dist/blog/2020/01/14/a/assets/masked.webp "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);           
}
```

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.

---

## About Bjoern Meyer

As CEO, Bjoern is the visionary behind our strategic direction and business development, bridging the gap between our customers and engineering teams. His deep passion for coding and web technologies drives the creation of innovative products. If you're at a tech conference, be sure to stop by our booth - you'll most likely meet Bjoern in person. With an advanced graduate degree (Dipl. Inf.) in Computer Science, specializing in AI, from the University of Bremen, Bjoern brings significant expertise to his role. In his spare time, Bjoern enjoys running, paragliding, mountain biking, and playing the piano.

- [LinkedIn](https://www.linkedin.com/in/bjoernmeyer/)
- [X](https://x.com/txbjoern)
- [GitHub](https://github.com/bjoerntx)

---

## Related Posts

- [Getting Started: Creating a .NET 8 Windows Forms Ribbon Application with Sidebar Support](https://www.textcontrol.com/blog/2024/02/28/getting-started-creating-a-net-8-windows-forms-ribbon-application-with-sidebar-support/llms.txt)
- [Table Extension: Remove Empty Columns After Mail Merge](https://www.textcontrol.com/blog/2023/06/08/table-extension-remove-empty-columns-after-mail-merge/llms.txt)
- [An Ultimate Guide to Mail Merge with MS Word Documents in C#](https://www.textcontrol.com/blog/2023/06/07/an-ultimate-guide-to-mail-merge-with-ms-word-documents-in-csharp/llms.txt)
- [Mail Merge with MS Word Documents in C# - An Ultimate Guide](https://www.textcontrol.com/blog/2022/05/25/mail-merge-with-ms-word-documents-in-csharp-an-ultimate-guide/llms.txt)
- [Combining MailMerge and Table of Contents](https://www.textcontrol.com/blog/2022/03/22/combining-mailmerge-and-table-of-contents/llms.txt)
- [Merging Form Fields using the MailMerge Class](https://www.textcontrol.com/blog/2022/02/21/merging-form-fields-using-the-mailmerge-class/llms.txt)
- [MailMerge: Rendering Conditional Table Rows](https://www.textcontrol.com/blog/2022/02/17/mailmerge-rendering-conditional-table-rows/llms.txt)
- [Merging Merge Block Cells Vertically with Matching Content](https://www.textcontrol.com/blog/2021/10/20/vertically-merge-table-cells-of-merge-blocks-for-matching-content/llms.txt)
- [Merge Excel Documents into MailMerge Templates using IncludeText Fields](https://www.textcontrol.com/blog/2019/08/13/merge-excel-documents-into-mailmerge-templates/llms.txt)
- [Using MailMerge with Chart Objects and JSON Data](https://www.textcontrol.com/blog/2019/07/18/using-mailmerge-with-chart-objects-and-json-data/llms.txt)
- [MailMerge: Conditional Table Cell Colors using Filter Instructions](https://www.textcontrol.com/blog/2019/06/06/mailmerge-conditional-table-cell-colors-using-filter-instructions/llms.txt)
- [MailMerge: Using Filters to Remove Unwanted Rows](https://www.textcontrol.com/blog/2019/06/04/mailmerge-using-filters-to-remove-unwanted-rows/llms.txt)
- [MailMerge: Conditional Rendering of Merge Blocks](https://www.textcontrol.com/blog/2018/11/28/mailmerge-conditional-rendering-of-merge-blocks/llms.txt)
- [DataSourceManager: Using the Ready-to-Use Reporting Dialog Boxes](https://www.textcontrol.com/blog/2018/11/27/datasourcemanager-using-the-ready-to-use-reporting-dialog-boxes/llms.txt)
- [Customizing the Windows Forms Ribbon](https://www.textcontrol.com/blog/2018/09/17/customizing-the-windows-forms-ribbon/llms.txt)
- [Using the Reporting RibbonTab](https://www.textcontrol.com/blog/2018/04/16/using-the-reporting-ribbontab/llms.txt)
- [Different Ways to Create Documents using Text Control Products](https://www.textcontrol.com/blog/2017/10/17/ways-to-create-documents-using-text-control-products/llms.txt)
- [Version X14: Customizing the Text Control Ribbon Control](https://www.textcontrol.com/blog/2017/01/02/version-x14-customizing-the-text-control-ribbon-control/llms.txt)
- [Adding Elements to the Ribbon QuickAccessToolbar](https://www.textcontrol.com/blog/2016/12/22/adding-elements-to-the-ribbon-quickaccesstoolbar/llms.txt)
- [Sneak Peek: Windows Forms Ribbon Bar Visual Studio Design-time Support](https://www.textcontrol.com/blog/2016/11/03/sneak-peek-windows-forms-ribbon-bar-visual-studio-design-time-support/llms.txt)
- [Windows Forms: Preview Mail Merge Results with the BindingNavigator and a BindingSource](https://www.textcontrol.com/blog/2016/01/08/windows-forms-preview-mail-merge-results-with-the-bindingnavigator-and-a-bindingsource/llms.txt)
