TX Text Control .NET for WPF

Integrating WPF Barcodes and Drawings

Topic

Barcodes and drawings sit in a WPF document like images: inline in the text, anchored to a paragraph or at a fixed position on the page. Each is a frame in the document that holds a WPF element drawing its content -- a barcode control for barcodes, a drawing control with shapes for drawings. Both come with the TX Text Control package, so no further reference is needed. The sections below show how the parts fit together, how the ribbon offers them to users, and how your code inserts them.

The WPF TextControl has no chart objects: it has no Charts collection and no ribbon tab for charts, which the Windows Forms product has. How users format and position barcodes in the editor is described in Charts and Barcodes and Text Frames and Shapes.

What Each Object Is Made of

BarcodeDrawing
The object in the documentBarcodeFrameDrawingFrame
The WPF element that draws itTXBarcodeControl in TXTextControl.WPF.BarcodeTXDrawingControl in TXTextControl.WPF.Drawing, which holds Shape objects
All of them in the text part with the input focusTextControl.BarcodesTextControl.Drawings
The assembliesTXBarcode.dll and TXBarcode.WPF.dllTXDrawing.dll and TXDrawing.WPF.dll

The frame, in the namespace TXTextControl.DataVisualization, handles the position in the text; the element holds the content, such as the barcode type and its data or the shapes of a drawing. The collections of the TextControl refer to the text part with the input focus: the main text, a header or footer, or a text frame. The class diagram of the barcode classes shows the frame, the collection and the two barcode controls for Windows Forms and WPF:

A class diagram of the barcode classes: TextControl and WPF.TextControl with the Barcodes property, BarcodeCollection, BarcodeFrame, TXBarcodeControl and WPF.TXBarcodeControl, and BarcodeTypeSettings.

The package TXTextControl.TextControl.WPF.SDK contains all four assemblies. A window that declares a barcode or drawing element in XAML maps its namespace with a prefix of its own, as Assemblies and XAML Namespaces shows; usually, they are created in code.

Offer Barcodes and Drawings in the Ribbon

The RibbonInsertTab has an item that inserts a barcode, TXITEM_InsertBarcode, and a drop-down for shapes, TXITEM_InsertShape. The drop-down lists the shapes in categories, such as lines, rectangles, basic shapes, block arrows, equation shapes, flowchart shapes, stars and banners, and callouts, and has an item for a drawing canvas that holds several shapes, TXITEM_InsertDrawingCanvas. The RibbonFrameLayoutTab edits the layout of selected images, text frames, drawings and barcodes.

Connect both tabs to the editor by name, through RibbonInsertTab and RibbonFrameLayoutTab of the TextControl, as Connecting Ribbon Tabs in XAML shows. Without a ribbon, BarcodeLayoutDialog and DrawingLayoutDialog open dialog boxes for the layout of the selected object.

Insert a Barcode in Code

Code inserts a barcode in two steps: it sets the type and the text of a WPF TXBarcodeControl and adds a BarcodeFrame that holds it to TextControl.Barcodes. The text position -1 inserts the barcode inline at the input position; other overloads anchor it to a paragraph or place it at a fixed position. Insert a Barcode From Code shows the code, the barcode types and how to change the text of the selected barcode.

Insert a Drawing in Code

A drawing is inserted the same way: a TXDrawingControl, a canvas that holds one or more shapes, goes into a DrawingFrame, which TextControl.Drawings adds to the document. Insert a Shape From Code inserts a single shape that fills its drawing. Shape and ShapeType are shared with Windows Forms, in TXTextControl.Drawing, while the drawing classes of WPF and Windows Forms differ in a few members, such as the context menu of shapes; the class diagram on that page marks them.

The examples below add their buttons to a window with a TextControl named textControl1 and their handlers to MainWindow.xaml.cs.

Work With the Shapes of a Drawing

The shapes of a drawing are programmed through its TXDrawingControl: its Shapes hold the shapes, its Selection the shapes the user selected, and its events report what happens to a shape. For a drawing that is already in the document, DrawingFrame.Drawing returns the drawing control; it is typed object, so cast it to the WPF class.

Draw Shapes With a Fill and an Outline

The following handler inserts a drawing canvas with two overlapping shapes and reports each shape the user selects:

using System.Windows;
using TXTextControl.DataVisualization;
using TXTextControl.Drawing;
using TXTextControl.WPF.Drawing;

private void insertCanvasButton_Click(object sender, RoutedEventArgs e)
{
    TXDrawingControl drawing = new TXDrawingControl();

    // A canvas of 2 x 1 inches, in twips
    drawing.SetCanvasSize(2880, 1440);

    TXTextControl.Drawing.Shape box = new TXTextControl.Drawing.Shape(ShapeType.RoundRectangle)
    {
        Location = new System.Drawing.Point(144, 144),
        Size = new System.Drawing.Size(1800, 1000)
    };
    box.ShapeFill.Color = System.Drawing.Color.LightSteelBlue;
    box.ShapeOutline.Color = System.Drawing.Color.DarkBlue;
    box.ShapeOutline.Width = 40;

    TXTextControl.Drawing.Shape star = new TXTextControl.Drawing.Shape(ShapeType.Star5)
    {
        Location = new System.Drawing.Point(1440, 288),
        Size = new System.Drawing.Size(1000, 1000),
        Angle = 15
    };
    star.ShapeFill.Color = System.Drawing.Color.Gold;

    // Each shape is drawn at its own location and size
    drawing.Shapes.Add(box);
    drawing.Shapes.Add(star);

    drawing.ShapeSelected += Drawing_ShapeSelected;

    textControl1.Drawings.Add(new DrawingFrame(drawing), -1);
    textControl1.Focus();
}

private void Drawing_ShapeSelected(object sender, ShapeEventArgs e)
{
    TXTextControl.Drawing.Shape shape = e.Shape;
    Title = $"{shape.Type}: {shape.Size.Width} x {shape.Size.Height} twips, angle {shape.Angle}";
}

The code works as follows:

  • SetCanvasSize sets the width and height of the canvas in twips, at a zoom factor of 100 percent.
  • Location and Size of a shape are in twips from the top-left corner of the canvas, and Angle rotates it. ShapeCollection.Add without an AddStyle draws the shape at that location and size.
  • ShapeFill and ShapeOutline are read-only properties that return objects of the nested classes Shape.Fill and Shape.Outline. Their Color is a System.Drawing.Color, and the outline Width is in twips, 20 by default.
  • ShapeSelected passes a ShapeEventArgs whose Shape is the selected shape.
  • Shape is written with its namespace because System.Windows.Shapes, which the WPF project template imports, has a Shape class too.

Shapes have further properties: Movable and Sizable, both true by default, decide whether users can move and size a shape; IsSelected and Index tell whether a shape is selected and where it is in the collection; FitToCanvas expands a shape to the size of the canvas when CanFitToCanvas is true.

Change the Z-Order of Selected Shapes

The order of the shapes decides which one covers another. Drawing.Selection changes it for the selected shapes:

MethodMoves the selected shapesPossible when
BringForwardOne level upCanBringForward is true
SendBackwardOne level downCanSendBackward is true
BringToFrontAbove all other shapes; one shape onlyCanBringToFront is true
SendToBackBelow all other shapes; one shape onlyCanSendToBack is true

A method has no effect while its Can property is false, for example when no shape is selected. The shapes of a drawing can be selected when the user has activated it with a click. The following button brings the selected shape of the activated drawing to the front; Focusable="False" keeps the keyboard focus in the editor while the button is clicked:

<Button Content="Bring to Front" Focusable="False" Click="bringToFrontButton_Click" />
private void bringToFrontButton_Click(object sender, RoutedEventArgs e)
{
    // The drawing the user activated, or null
    DrawingFrame frame = textControl1.Drawings.GetActivatedItem();

    if (frame?.Drawing is TXDrawingControl drawing && drawing.Selection.CanBringToFront)
    {
        drawing.Selection.BringToFront();
    }
}

DrawingCollection.GetActivatedItem returns the activated drawing. Selection.Shapes sets the selection in code, and TXDrawingControl.SelectAll selects every shape. The TextControl reports the activation with DrawingActivated, whose DrawingEventArgs.DrawingFrame is the drawing; its handler is the place to attach shape events to drawings loaded with a document.

Events and Members of the Drawing Control

MemberPurpose
ShapeCreated, ShapeDeletedA shape was added by pasting or Add, or removed by cutting or Remove
ShapeSelected, ShapeDeselected, ShapeClickedA shape was selected, deselected or clicked
ShapeMoved, ShapeSized, ShapeFlipped, ShapeAdjustedThe user moved, sized or flipped a shape with the mouse, or changed it with its yellow adjust handle
ShapeFormatChangedThe fill, outline or type of a shape changed
Changed, ViewChangedThe number or formatting of the shapes changed, or the view changed, with the changed area in ViewChangedEventArgs
AdaptBounds, SizeToContentThe visible bounds of the shapes need a larger or smaller control, and the method that adapts the control to them
IsCanvasVisiblefalse when the control holds a single shape that it represents, without a border or canvas of its own
FormatShapesDialogOpens the dialog box that formats the selected shapes; returns null when no shape is selected
Undo, Redo, Copy, Cut, PasteUndo and clipboard operations for the shapes of the drawing
ZoomFactor, BackColor, BorderColor, BorderWidthThe zoom factor of the drawing and the background and border of the canvas
Save, Load, SaveImageSave the shape data to a stream and load it again, or save the shapes as an image

TXDrawingCore

TXDrawingCore, in TXTextControl.Drawing since version 33.0, is a canvas of shapes without a user interface. It has Shapes, Selection, most of the shape events and the undo and clipboard members of the drawing control, and renders the shapes as SVG with GetSVG. The DrawingFrame constructor takes the drawing controls of Windows Forms and WPF, so a drawing inserted into the WPF TextControl uses TXDrawingControl.

Create a Barcode as SVG With TXBarcodeCore

TXBarcodeCore, in TXTextControl.Barcode since version 33.0, is the barcode counterpart of TXDrawingCore: a barcode without a WPF element. It has the type, text and appearance properties of TXBarcodeControl and returns the barcode as an SVG string, for example for a web page, an email or an image file. The BarcodeFrame constructor takes the barcode controls only, so a barcode that users should edit in the document is inserted as in Insert a Barcode in Code. The SVG of a TXBarcodeCore goes into a document as an image:

using System.IO;
using System.Windows;
using TXTextControl.Barcode;

private void insertSvgBarcodeButton_Click(object sender, RoutedEventArgs e)
{
    const string orderNumber = "ORD-2025-0042";

    // Initialize the new instance before using it
    TXBarcodeCore barcode = new TXBarcodeCore();
    barcode.Create();
    barcode.BarcodeType = BarcodeType.Code128;
    barcode.UpperTextLength = orderNumber.Length;
    barcode.Text = orderNumber;

    // The barcode as an SVG image; Size is System.Drawing.Size, not the WPF Size
    string svg = barcode.GetSVG(new System.Drawing.Size(4320, 1080));
    File.WriteAllText("order-barcode.svg", svg);

    // 8 is the import filter for SVG
    textControl1.Images.Add(new TXTextControl.Image("order-barcode.svg", 8), -1);
}

The code works as follows:

  • Create initializes the object and must be called before any other member.
  • BarcodeType is set first, because UpperTextLength, the maximum number of characters, and Text throw an ArgumentException when the value isn't valid for the type.
  • GetSVG returns the SVG in the given size, which also becomes the Size of the object.
  • The image is inserted inline at the input position, as Images describes. TXTextControl.Image is written in full because Image alone is the WPF image element. The result is an image in the document, not a barcode that BarcodeLayoutDialog or the ribbon can change.

Before you set Text from user input, the static IsTextValid tells whether a text is valid for a barcode type and returns the error message if not. GetDefaultText returns a valid sample text, and GetMinimumTextLength and GetMaximumTextLength the shortest and longest text of a type. Save writes the settings of the barcode to a file or a Stream, and Load reads them into a TXBarcodeCore again.

Merge Data Into Barcodes

Barcodes in a template get their data in a mail merge, like merge fields. Images and Barcodes in the Mail Merge section shows how templates with barcodes are merged with MailMerge.

Next Steps