Charts and Barcodes
A QR code that links an invoice to a customer portal, a Code 128 barcode with an order number on a packing slip and a bar chart of the quarter's sales are frames that TX Text Control places in a document like images. In a Windows Forms application, your code creates them, positions them, changes their data later and removes them. Barcodes work with the NuGet package alone, while charts need the chart control of Windows Forms, which the last sections explain.
Users insert barcodes and charts from the ribbon, as described in Charts and Barcodes, and Integrating Charts and Barcodes covers the references and controls your project needs. Barcodes and charts that a mail merge fills with data are the subject of Images and Barcodes. Frames are positioned as Images, Text Frames, and Shapes describes. Form1.cs needs these using directives:
using System;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
using TXTextControl;
using TXTextControl.Barcode;
using TXTextControl.DataVisualization;
The System.Windows.Forms.DataVisualization.Charting directive is needed only for charts.
How Barcodes Work
A barcode in a document consists of two objects:
- TXBarcodeControl holds the barcode: its BarcodeType, the encoded text and its appearance. Despite its name, the Windows Forms class isn't a control on your form; you create it in code.
- BarcodeFrame places the barcode in the document with a name, an ID, a size and a position, like an image.
Barcodes returns the BarcodeCollection of the text part with the input focus. A header has its own, HeaderFooter.Barcodes, for a code that appears on every page. Barcodes are part of the Enterprise and Professional editions; see Editions and Feature Availability.
The following packing slip shows the kinds of codes this page creates: a QR code at the top and a linear barcode in each row of the item table.

Insert a QR Code
The following handler anchors a dark blue QR code with a link at the right edge of the paragraph with the input position:
private void insertQrCodeButton_Click(object sender, EventArgs e)
{
const string portalLink = "https://www.textcontrol.com";
// The barcode: type first, then the length and the text
TXBarcodeControl qrCode = new TXBarcodeControl();
qrCode.BarcodeType = BarcodeType.QRCode;
qrCode.UpperTextLength = portalLink.Length;
qrCode.Text = portalLink;
qrCode.ForeColor = Color.DarkBlue;
// The frame places the barcode in the document, 1 x 1 inch
BarcodeFrame qrFrame = new BarcodeFrame(qrCode)
{
Name = "portal-link",
Size = new Size(1440, 1440)
};
// Anchored to the paragraph at the input position, the text flows around it
textControl1.Barcodes.Add(qrFrame, TXTextControl.HorizontalAlignment.Right, -1,
FrameInsertionMode.DisplaceText);
}
The code works as follows:
- UpperTextLength is the maximum number of characters and Text the encoded text. Both throw an
ArgumentExceptionwhen the value isn't valid for the barcode type, so set the type first. - ForeColor and BackColor are the colors of the code and its background, and Angle rotates it.
- The BarcodeFrame constructor takes the barcode, and
Sizeis the size of the frame in twips. - BarcodeCollection.Add has the placements of all frames.
DisplaceText, a value of FrameInsertionMode, lets the text flow around the code.
Insert a Barcode With Text
A linear barcode can show its text below or above the bars. The following handler checks an invoice number, then inserts it as a Code 128 barcode inline with the text:
private void insertBarcodeButton_Click(object sender, EventArgs e)
{
string invoiceNumber = "INV-2025-001";
// Check the text before it is assigned
string errorMessage;
if (!TXBarcodeControl.IsTextValid(BarcodeType.Code128, invoiceNumber, out errorMessage))
{
MessageBox.Show(errorMessage);
return;
}
TXBarcodeControl code128 = new TXBarcodeControl();
code128.BarcodeType = BarcodeType.Code128;
code128.UpperTextLength = invoiceNumber.Length;
code128.Text = invoiceNumber;
code128.ShowText = true;
code128.AdditionalText = "Invoice number";
code128.TextAlignment = TextAlignment.Bottom;
// Inline, like a single character, at the input position
textControl1.Barcodes.Add(new BarcodeFrame(code128) { Size = new Size(4320, 1080) }, -1);
}
- The static IsTextValid checks a text for a barcode type and returns the error message when it isn't valid, which is safer than catching the exception of
Textwhen the value comes from a user. - ShowText shows the encoded text of a one-dimensional barcode, and AdditionalText adds a text of your own. TextAlignment puts both at the
Bottom, the default, or theTop.
To show a code on every page, add it to the header, for example header.Barcodes.Add(frame, TXTextControl.HorizontalAlignment.Right, -1, FrameInsertionMode.AboveTheText). To place it on one page, use the overload with a page number and a location: textControl1.Barcodes.Add(frame, 1, new Point(8640, 720), FrameInsertionMode.AboveTheText).
Change and Remove Barcodes
BarcodeFrame.Barcode returns the barcode of a frame. Changes to the barcode aren't shown until you call Refresh:
private void updateBarcodeButton_Click(object sender, EventArgs e)
{
// null if no barcode has this name
BarcodeFrame frame = textControl1.Barcodes.GetItem("portal-link");
if (frame == null)
{
return;
}
TXBarcodeControl barcode = (TXBarcodeControl)frame.Barcode;
barcode.UpperTextLength = 40;
barcode.Text = "https://www.textcontrol.com/blog/";
// Changes to the barcode are shown after Refresh
frame.Refresh();
}
BarcodeCollection.GetItem returns a barcode by its name or ID, or null, and Remove deletes it from the document. The BarcodeCreated and BarcodeDeleted events of the TextControl report barcodes that are created and deleted. Programmatic changes to a barcode aren't added to the undo history of the editor; AddUndoUnit adds the current state of the barcode to it.
TXBarcodeControl.SaveImage writes a barcode to an image file or a stream, for example barcode.SaveImage("qrcode.png", System.Drawing.Imaging.ImageFormat.Png).
Add Charts
A chart in a document is a ChartFrame. The frame places the chart, while the chart itself is a chart control of the type System.Windows.Forms.DataVisualization.Charting.Chart, which holds its appearance and data. Microsoft didn't port this library to .NET, so a .NET project references a port of it before it can use charts. Migrating from .NET Framework to .NET describes how to build and install the package from Text Control's fork.
The following handler binds a chart to a DataTable and inserts it at the input position. The code follows Text Control's how-to sample for charts, installed with the product under Howto\Charts:
private void insertChartButton_Click(object sender, EventArgs e)
{
// Sample data: one row per country
DataTable sales = new DataTable("sales");
sales.Columns.Add("Country", typeof(string));
sales.Columns.Add("Value", typeof(int));
sales.Rows.Add("United States", 100);
sales.Rows.Add("Germany", 120);
sales.Rows.Add("Japan", 140);
// A chart control with one series and one chart area
Chart chart = new Chart();
chart.Series.Add("series1");
chart.ChartAreas.Add("area1");
// Bind the series to the columns of the table
chart.DataSource = sales;
chart.Series[0].XValueMember = "Country";
chart.Series[0].YValueMembers = "Value";
chart.DataBind();
// The frame places the chart in the document
ChartFrame chartFrame = new ChartFrame(chart);
chartFrame.Name = "sales";
textControl1.Charts.Add(chartFrame, -1);
}
The code works as follows:
Series,ChartAreas,DataSource,XValueMember,YValueMembersandDataBindbelong to the chart control, not to TX Text Control.- The ChartFrame constructor takes the chart. Like a text field, the frame has a Name that identifies the chart, here the name of the data it shows.
- Charts returns the ChartCollection of the text part with the input focus, and Add inserts the frame like an image.
Fill the Charts of a Template With Data
The second part of the how-to sample loads a template with named charts and fills each chart from the table of a DataSet with the same name:
private void mergeChartsButton_Click(object sender, EventArgs e)
{
DataSet data = new DataSet();
data.ReadXml("Data.xml");
foreach (ChartFrame chartFrame in textControl1.Charts)
{
// Only charts named like a table of the data set
if (!data.Tables.Contains(chartFrame.Name))
{
continue;
}
DataTable table = data.Tables[chartFrame.Name];
Chart chart = (Chart)chartFrame.Chart;
// The first two columns are the x and y values
chart.Series[0].XValueMember = table.Columns[0].ColumnName;
chart.Series[0].YValueMembers = table.Columns[1].ColumnName;
chart.DataSource = table;
chart.DataBind();
// Show the new data in the document
chartFrame.Refresh();
}
}
ChartFrame.Chart returns the chart control, and ChartFrame.Refresh shows the changed chart. The result in the sample is a bar chart of the data:

A mail merge fills charts of a template as well, and MailMerge.ChartMerged occurs for each chart it has merged; the blog article Using MailMerge with Chart Objects and JSON Data connects a chart to data this way. The blog article Using Charts with TX Text Control .NET for Windows 31.0 in .NET 6 shows the chart package in a .NET project with screenshots.
Next Steps
- Images, Text Frames, and Shapes: the other kinds of frames.
- Charts and Barcodes: charts and barcodes from the user's side.
- Integrating Charts and Barcodes: the references and controls a project needs.
- Images and Barcodes: fill barcodes of a template with data.