# DataSets and DataTables

> Merge DataTables and related tables of a DataSet in a WPF window, load them into the Reporting tab and edit relations with the WPF EditDataRelationsDialog.

- **Product:** TX Text Control .NET for WPF
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET for WPF > Mail Merge and Reporting > Data Sources > DataSets and DataTables
- **2715 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/datasets/llms-full.txt

---

A `DataTable` filled from a query, or a `DataSet` that holds several of them with their relations, is a ready-made data source for `MailMerge`. The column names become field names, and the relations decide which rows fill the merge blocks of each master record. Below, you merge a single table and related tables in a WPF window, make the tables available in the **Reporting** tab and let users edit relations there.

The examples turn the invoice of the [Mail Merge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/getting-started/mail-merge/llms-full.txt) tutorials into two tables: `Invoice`, with the columns `Company`, `Name` and `InvoiceNumber`, and `Items`, which fills the merge block `Items`.

### Merge a DataTable

[Merge](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/merge-method/llms-full.txt) takes a `DataTable`, uses its column names as field names and merges the template once for each row. Its second parameter, `append`, combines the results into one document when it is `true` and keeps them separate when it is `false`.

### Merge Related Tables

The rows of `Items` belong to a row of `Invoice`. Put both tables in a `DataSet`, add a `DataRelation` that connects them and pass the master table to `Merge`. `Merge` follows the relations: the merge block `Items` receives the related rows of the table with that name, and merge fields can address a related table with its name as prefix, such as `Customer.City`.

The following methods of *MainWindow.xaml.cs* build the data and merge it into the template in `textControl1` when the user clicks a button named `mergeDataSetButton`:

```csharp
using System.Data;
using System.Windows;
using TXTextControl.DocumentServer;
```

```csharp
private DataSet CreateInvoiceData()
{
    DataSet dataSet = new DataSet();

    DataTable invoice = dataSet.Tables.Add("Invoice");
    invoice.Columns.Add("InvoiceId", typeof(int));
    invoice.Columns.Add("Company");
    invoice.Columns.Add("Name");
    invoice.Columns.Add("InvoiceNumber");
    invoice.Rows.Add(1, "Contoso Ltd.", "Jane Miller", "INV-1001");

    DataTable items = dataSet.Tables.Add("Items");
    items.Columns.Add("InvoiceId", typeof(int));
    items.Columns.Add("Description");
    items.Columns.Add("Quantity", typeof(int));
    items.Columns.Add("Price", typeof(decimal));
    items.Rows.Add(1, "Consulting", 2, 150.00m);
    items.Rows.Add(1, "Training", 1, 480.00m);

    // The relation connects each invoice with its items
    dataSet.Relations.Add("InvoiceItems", invoice.Columns["InvoiceId"], items.Columns["InvoiceId"]);

    return dataSet;
}

private void mergeDataSetButton_Click(object sender, RoutedEventArgs e)
{
    DataSet dataSet = CreateInvoiceData();

    using (MailMerge mailMerge = new MailMerge { TextComponent = textControl1 })
    {
        // Pass the master table; the related Items table fills the Items block
        mailMerge.Merge(dataSet.Tables["Invoice"], true);
    }
}
```

The code works as follows:

- `InvoiceId` is the key column of the relation. The template doesn't need a field for it.
- `dataSet.Relations.Add` connects the parent column with the child column. Without the relation, the `Items` block gets no rows, and its content is removed, because [RemoveEmptyBlocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/removeemptyblocks-property/llms-full.txt) is `true` by default.
- `Merge` merges one invoice per row of `Invoice`, with its items, and the WPF `TextControl` shows the result.

In a real application, a `DataAdapter` fills the tables from the database, and your code adds the relations in the same way. Relations over further levels, such as from an item to its product, feed nested merge blocks and prefixed fields like `Production_Product.Name`; the blog article [Prefixed Merge Field Names using Related Tables](https://www.textcontrol.com/blog/2014/07/03/prefixed-merge-field-names-using-related-tables/) shows a template that uses them.

### Offer the Tables in the Reporting Tab

The [DataSourceManager](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-wpf/ribbonreportingtab/datasourcemanager-property/llms-full.txt) of the WPF Reporting tab loads a `DataSet` with its relations through [LoadDataSet](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/loaddataset-method/llms-full.txt), and a single table through [LoadDataTable](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/loaddatatable-method/llms-full.txt). Load the data when the `TextControl` has loaded, in a handler connected with `Loaded="textControl1_Loaded"` on the `TextControl` element:

```csharp
private void textControl1_Loaded(object sender, RoutedEventArgs e)
{
    ribbonReportingTab1.DataSourceManager.LoadDataSet(CreateInvoiceData());
}
```

**Select Master Table** then chooses the table whose columns **Insert Merge Field** lists, and **Insert Merge Block** offers the tables related to it. In code, [PossibleMergeBlockTables](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/possiblemergeblocktables-property/llms-full.txt) returns these tables for the current master table.

### Edit Relations in the Designer

**Edit Data Relations** in the **Data Source** group of the Reporting tab lets users add relations the loaded data lacks, by choosing a main table, a child table and the columns that connect them. The dialog box behind the button is [EditDataRelationsDialog](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-wpf/editdatarelationsdialog/llms-full.txt) of the `TXTextControl.DocumentServer.WPF` namespace, a WPF `Window` that your code can open too. [DataRelations](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver-datasources/datasourcemanager/datarelations-property/llms-full.txt) lists the relations afterward:

```csharp
using System.Diagnostics;
using System.Windows;
using TXTextControl.DocumentServer.DataSources;
using TXTextControl.DocumentServer.WPF;
```

```csharp
private void relationsButton_Click(object sender, RoutedEventArgs e)
{
    DataSourceManager dataSourceManager = ribbonReportingTab1.DataSourceManager;

    // A modal WPF window, owned by the main window
    EditDataRelationsDialog dialog = new EditDataRelationsDialog(dataSourceManager) { Owner = this };
    dialog.ShowDialog();

    foreach (DataRelationInfo relation in dataSourceManager.DataRelations)
    {
        Debug.WriteLine($"{relation.ParentTableName} -> {relation.ChildTableName}");
    }
}
```

The relations created this way belong to the `DataSourceManager`, the data of the designer. A WPF application can't save them in a data source configuration file, as [Data Source Configuration Files](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/configuration-files/llms-full.txt) explains; add the same relations to the `DataSet` your code merges.

### Replace MergeBlocks in Older Code

Older code may call [MergeBlocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/reference/txtextcontrol-documentserver/mailmerge/mergeblocks-method/llms-full.txt), which merges the blocks of a template with the tables of a `DataSet` named like the blocks. The method is obsolete: since version 20.0, `Merge` fills blocks from the related tables of the master table. [Deprecated APIs](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/whats-new/deprecated-apis/llms-full.txt) lists it with its replacement.

### Next Steps

- [JSON and XML](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/json-xml/llms-full.txt): XML files read into a `DataSet`, and JSON data.
- [Nested Blocks and Master-Detail Reports](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/nested-blocks/llms-full.txt): relations over several levels.
- [Merge Blocks](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/blocks/llms-full.txt): design the blocks that related tables fill.
- [Objects and Collections](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/objects/llms-full.txt): the same invoice as business objects.

---

## Nearby

- **Previous:** [Objects and Collections](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/objects/llms-full.txt)
- **Next:** [JSON and XML](https://docs.textcontrol.com/tx-text-control-dotnet-wpf/mail-merge/data-sources/json-xml/llms-full.txt)
