Show / Hide Table of Contents

Windows Label Editor

The Windows ThermalLabelEditor component is a first-class label designer for .NET Windows desktop apps. Its main goal is to help your users design labels in a visual environment, without you having to build the design surface yourself.

ThermalLabelEditor provides:

  • Visual creation tools for every label item type (text, barcodes, images, shapes, tables, repeaters, literals and RFID tags)
  • An undo/redo engine and Cut/Copy/Paste (internal or OS clipboard)
  • Z-ordering, grouping, alignment and distribution tools
  • Zooming, rulers, grid, and snapping to the grid or to nearby items
  • Rotation of the whole design view
  • Duplex (Front/Back) label design with a flip animation
  • In-place text editing for TextItem objects
  • Keyboard shortcuts for the well-known common actions
  • Deep visual customization, including saving/loading a "theme" as JSON, so you can skin it to match the app that hosts it

The following is a screenshot of the sample app shipped with the ThermalLabel SDK package.

WPF Windows Label Editor for WPF

Windows Forms Windows Label Editor for Windows Forms

In the screenshot, pay attention to the area surrounded by the rulers (inside the red rectangle): that is the ThermalLabelEditor component. The rest of the UI (menu, toolbar, status bar, property dialogs, etc.) is designed and coded by you. You can build a Visual Label Designer inside your own WPF or Windows Forms app using whatever UI you prefer: a Ribbon instead of a standard menu, dialog boxes instead of a "Properties Window/Grid", and so on. You are free to surround the ThermalLabelEditor component to match your app's style.

Note

This page groups the editor's features by topic and shows how to use the most important ones. The full list of classes, properties, methods and events is in the API Reference.


System Requirements

  • ThermalLabel Windows Editor (Neodynamic.Windows.ThermalLabelEditor.dll)
  • ThermalLabel SDK 16.0 (Neodynamic.SDK.ThermalLabel.dll)
  • ThermalLabel SDK 16.0 Windows Printing (Neodynamic.SDK.ThermalLabel.WindowsPrinting.dll)
  • .NET Framework 4.6.1+ or .NET Core 3.1+
  • SkiaSharp 1.68.3+
  • System.Text.Encoding.CodePages 4.4.0+

The editor draws its items with SkiaSharp, so the SkiaSharp package must be referenced by your project.

.NET Assemblies and Namespaces

The editor ships in a WPF version and a Windows Forms version. Both are in the same assembly, Neodynamic.Windows.ThermalLabelEditor.dll:

Platform Class
WPF Neodynamic.Windows.WPF.ThermalLabelEditor.ThermalLabelEditor
Windows Forms Neodynamic.Windows.Forms.ThermalLabelEditor.ThermalLabelEditor

Almost everything in this page applies to both; the differences are called out where they matter (for example, WPF uses Color/Brush values from System.Windows.Media, while Windows Forms uses System.Drawing.Color).

Types shared by both editions (enums, event args, settings classes, LabelDocument) live in the Neodynamic.Windows.ThermalLabelEditor namespace. WPF routed commands live in Neodynamic.Windows.WPF.ThermalLabelEditor.EditorCommands.

Licensing

Set your license before the first editor is created:

Neodynamic.Windows.WPF.ThermalLabelEditor.ThermalLabelEditor.LicenseOwner = "YOUR-LICENSE-OWNER";
Neodynamic.Windows.WPF.ThermalLabelEditor.ThermalLabelEditor.LicenseKey   = "YOUR-LICENSE-KEY";

In the Windows Forms edition, use the same static properties on Neodynamic.Windows.Forms.ThermalLabelEditor.ThermalLabelEditor. Without a valid license, the editor runs in trial mode and displays a trial notice on its surface.

Sample Application Projects

The ThermalLabel SDK repo on GitHub provides Windows Forms and WPF projects that use the ThermalLabelEditor component. Open them with Visual Studio to learn how the component works and how to interact with it from your own app. The Windows Forms project uses a "Properties Window" approach to let the user change the data of each item on the label, while the WPF project uses a "Properties Dialog" approach for the same task.

Important

The two sample projects are very simple and do NOT demo ALL the ThermalLabel SDK and Editor features! They might contain errors, bugs or bad software development practices, so do not treat them as a model of how to structure an app. They were written only to demo how to interact with the ThermalLabelEditor component. They are NOT part of our product; they are a sample of how your own code can talk to it.


Getting Started

The editor works on a ThermalLabel object from the ThermalLabel SDK. You load a label into the editor, the user edits it visually, and you get a ThermalLabel back to save or print.

using Neodynamic.SDK.Printing;

// 1. Load a label (an existing one, or a new one)
ThermalLabel tl = ThermalLabel.CreateFromXmlTemplate(File.ReadAllText("label.xml"));
editor.LoadThermalLabel(tl);

// 2. ...the user designs on the surface...

// 3. Get the edited label back
ThermalLabel edited = editor.CreateThermalLabel();

// ...or save it directly (XML or JSON)
editor.Save(@"C:\labels\label.xml");
editor.SaveAsJson(@"C:\labels\label.json");

Key concepts:

  • LabelDocument: a lightweight description of the label being edited (unit, size, margins, pages, duplex flag, etc.), created automatically by LoadThermalLabel(). To change those settings on the open label, call UpdateLabelDocument().
  • Items: the editor works on the SDK Item classes. You can add items from code with AddItem(), InsertItem(), AddItemsRange() and InsertItemsRange().
  • Item index: the index of an item is its position in CreateThermalLabel().Items. The ...ByIndex / ...ByIndexes methods use this index space.
  • Close the label: call Close() to close the current label document.

Item Creation Tools

The user (or your toolbar) creates items by activating a tool and then drawing on the surface. Set ActiveTool to one of the EditorTool values and provide a template item in ActiveToolItem; the editor clones that item every time the user draws a new one.

EditorTool Item type expected in ActiveToolItem
Pointer (none) The default tool, used for selecting and transforming items
Rectangle RectangleShapeItem
Ellipse EllipseShapeItem
Line LineShapeItem
Text TextItem
Barcode BarcodeItem
Image ImageItem
Literal LiteralItem
RFIDTag RFIDTagItem
Table TableShapeItem
Repeater RepeaterItem
// Let the user draw a Code 128 barcode
editor.ActiveToolItem = new BarcodeItem { Symbology = BarcodeSymbology.Code128, Code = "12345" };
editor.ActiveTool = EditorTool.Barcode;
// After the item is drawn, the editor goes back to the Pointer tool automatically.
Note

The type of ActiveToolItem must match ActiveTool, otherwise the editor throws an exception when the user starts drawing. Handle NewItemCreated to react when an item has been created.

Component Tray. RFIDTagItem and LiteralItem have no visual footprint on the printed label. Instead of floating over the label, they are shown as icons in a component tray docked below the label. Items in the tray are anchored (they can't be dragged or nudged) and are shared by both sides of a duplex label. The tray's look is customizable (see Visual Customization).


Selection

  • Click an item to select it. CTRL + click adds/removes items from the selection.
  • Rubber-band selection: drag a rectangle on the surface. By default an item must be fully inside the rectangle; set AllowPartialHitTestSelection = true to select every item the rectangle touches.
  • Groups: items that belong to the same group (see Grouping) are always selected together.
  • Select from code: SelectAll(), UnselectAll(), SelectItemByName(), SelectItemsByNames(), SelectItemsByTag(), SelectItemByIndex(), SelectItemsByIndexes() and SelectItemsByType() (for example "TextItem", "BarcodeItem"). GetSelectedItemsIndexes() returns the indexes of the selected items.
  • Keyboard focus: CTRL + SHIFT + LEFT / RIGHT moves the selection to the previous / next item.
  • Read the selection: handle SelectionChanged and read CurrentSelection (the selected items) and CurrentSelectionArea (the selection's location and size, available through SelectionAreaChanged).

Items that are not editable (Item.Editable = false) can't be selected, and locked items (Item.Locked = true) can be selected but not moved, resized or rotated.

Selection Handles (Adorners)

When items are selected, adorners appear around them: resize handles, a rotation handle, and a text legend with the item's position and size. Different item types get different adorners:

Adorner Used for
Basic Most items: 8 resize handles plus rotation
Line Line items: one handle per end point
Table Table items: resize handles plus column and row dividers
Fixed size Items whose size can't be changed by the user
Tray Component tray items

Hold SHIFT while resizing from a corner to keep the item's aspect ratio. Hold SHIFT while dragging the end of a line to constrain it to horizontal or vertical.

Out-of-Label Indicator

An item that is (even partly) outside the printable area of the label is outlined with a dashed frame. For round labels the printable area is the inscribed ellipse. Turn this on/off with AdornerOutOfLabelVisible and change its color with AdornerOutOfLabelColor.


Keyboard Shortcuts

Action / Operation Keyboard Shortcut KeyboardShortcuts flag
Clipboard Copy CTRL + C or CTRL + INSERT CtrlC
Clipboard Cut CTRL + X or SHIFT + DELETE CtrlX
Clipboard Paste CTRL + V or SHIFT + INSERT CtrlV
Undo CTRL + Z CtrlZ
Redo CTRL + Y CtrlY
Select All Items CTRL + A CtrlA
Delete Selected Items DELETE Delete
Move Selected Items (Small Step) ARROW KEYS (also I / J / K / L) ArrowKeys
Move Selected Items (Long Step) CTRL + ARROW KEYS ArrowKeys
Edit TextItem F2 F2
Leave text editing ESC
Select previous / next item CTRL + SHIFT + LEFT / RIGHT
Zoom In CTRL + PLUS SIGN or CTRL + MOUSE WHEEL UP CtrlPlus
Zoom Out CTRL + MINUS SIGN or CTRL + MOUSE WHEEL DOWN CtrlMinus
Zoom 100% CTRL + 0 (ZERO) CtrlZero

While a TextItem is in text-editing mode, the global shortcuts are not processed, so the text box keeps its normal editing behavior.

Disabling shortcuts. DisableShortcuts is a [Flags] enum, so you can switch off any combination. This is useful when your app already uses one of these keys for something else:

// Let the host app handle Delete and F2 itself
editor.DisableShortcuts = KeyboardShortcuts.Delete | KeyboardShortcuts.F2;

// Turn every shortcut off
editor.DisableShortcuts = KeyboardShortcuts.All;

Arrow-key step size. ArrowKeysShortStep (default 0.01 inch) and ArrowKeysLargeStep (with CTRL, default 0.1 inch) are expressed in the label's current unit. When SnapToGrid is on, each key press moves by one grid division instead.

WPF Routed Commands

For WPF apps, EditorCommands exposes the editor's actions as RoutedCommands, so you can bind menu items and toolbar buttons in XAML and get automatic enabled/disabled state through each command's CanExecute:

Undo, Redo, Cut, Copy, Paste, SelectAll, DeleteSelectedItems, DeleteAll, BringForward, BringToFront, SendBackward, SendToBack, LockSelectedItems, UnlockSelectedItems, SelectItemByName, SelectItemsByNames, UpdateSelectionItemsProperties, Save, SaveAsJson, Load, UpdateLabelDocument and RotateView.

<MenuItem Header="Undo" Command="ed:EditorCommands.Undo" CommandTarget="{Binding ElementName=labelEditor}" />
<MenuItem Header="Save" Command="ed:EditorCommands.Save" CommandParameter="C:\labels\label.xml"
          CommandTarget="{Binding ElementName=labelEditor}" />

Some commands need a CommandParameter: Save / SaveAsJson (file path or Stream), Load (XML template string or ThermalLabel), UpdateLabelDocument (a LabelDocument), RotateView (a Rotate value), SelectItemByName (string) and SelectItemsByNames (string[]).


Zooming

The editor supports high-quality zooming from 10% to 1000% through the Zoom property (default 100).

editor.Zoom = 200;   // 200%
editor.Zoom = 0;     // 0 means "fit the whole label (and its legend/tray) in the viewer"

Users can zoom with CTRL + MOUSE WHEEL, CTRL + PLUS, CTRL + MINUS and CTRL + 0 (each step is 10%).

For ImageItem objects, ImageProcessingDpi and ImageProcessingMonochromeDpi control the resolution used to process images on the surface. Leave them at 0 (Auto) to derive it from the zoom and monitor scale. Set ImageProcessingMonochromeDpi to your printer's resolution so the dithering you preview matches the printed output.


Rulers, Grid and Snapping

Rulers

There are two rulers, one along the top and one along the left side of the surface. The ruler unit automatically follows the unit of the label being edited, and the rulers highlight the position and size of the current selection. Show or hide them with ShowRuler. Their colors are customizable (see Visual Customization).

Grid

Property Description
ShowGrid Shows or hides the grid (default false)
GridSize Size of a grid division in the label's current unit
GridType GridType.Lines (default) or GridType.Dots
GridColor Color of the grid

Snap to Grid

With SnapToGrid = true, items are placed and sized according to the grid divisions as the user draws and moves them. Snapping is applied to items whose rotation is a multiple of 90 degrees. You can also snap on demand, regardless of the SnapToGrid setting: SnapToGridAll(), SnapToGridByCurrentSelection(), SnapToGridByItemName() and SnapToGridByItemIndex().

Snap to Items (Smart Guides)

With SnapToItems = true, dragging an item shows guide lines when its edges or its center line up with another item's edges or center (left, center and right edges horizontally; top, middle and bottom edges vertically). The item follows the mouse freely during the drag; when the user releases the mouse, it snaps to the closest guide. The snap distance is constant on screen (about 6 pixels), so it feels the same at any zoom level. Locked, hidden and component-tray items are ignored as snap targets. Change the guide color with GuidelineColor.

Angle Snap

AngleSnap (default 5 degrees) controls the rotation step when the user rotates an item with its rotation handle.


Grouping, Alignment and Sizing

  • Group / Ungroup: Group() and Ungroup() assign or clear a shared GroupName on the selected items. Clicking any item of a group selects the whole group, and pasting a group creates a new, independent group.
  • Alignment and distribution: LayoutSelectedItems(LayoutAlignment) aligns the selected items to the first one (Left, Right, Top, Bottom, CenterHorizontal, CenterVertical), or distributes them with equal spacing (DistributeHorizontal, DistributeVertical). With a single item selected, it aligns that item to the label itself.
  • Same size: SetSelectedItemsToSameSize(sameWidth, sameHeight) resizes the selected items to match the first one.
  • Move by code: MoveSelectedItems(deltaX, deltaY).
  • Lock / Unlock: LockSelectedItems() and UnlockSelectedItems() prevent accidental moves. Locked items show a lock icon.

Z-Ordering

Z-ordering is the position of an item in the Items collection of the ThermalLabel being edited. Use BringForward(), BringToFront(), SendBackward() and SendToBack() on the current selection.


In-Place Text Editing

Users can edit the text of a TextItem directly on the surface by double-clicking it or pressing F2; ESC leaves edit mode. In-place edition also works when the TextItem is rotated. Handle CurrentSelectionTextChanged to follow the text as the user types.

Set TextItemEditModeEnabled = false to disable in-place editing for all text items (for example, if your app edits text through its own dialog). Items with ReadOnly = true can't be edited in place.


Clipboard

Cut, Copy and Paste work on the selected items. ClipboardMode chooses where the data lives:

EditorClipboardMode Behavior
Internal (default) Items live only inside the editor instance. You can't paste them into another app.
System Items are also published to the OS Clipboard, so they can be pasted into another editor instance (MDI apps) or another application that hosts the editor.
editor.ClipboardMode = EditorClipboardMode.System;

Other things to know:

  • Cascading paste: each consecutive paste of the same selection is offset a little so the copies don't sit exactly on top of each other.
  • Cut keeps move semantics: if you cut, flip the duplex side and paste, the items move to the other side (see Duplex Label Design).
  • UI state: handle ClipboardStateChanged (or bind to the read-only CanCopy, CanCut and CanPaste properties) to enable/disable your buttons. In System mode, CanPaste follows the OS clipboard.
  • ClipboardItems() returns the items currently in the internal clipboard, and DisableClipboard turns the feature off.
Warning

ClipboardClear() also clears the Undo/Redo history.


Undo / Redo

The editor records a snapshot of the label after every user action (moving, resizing, rotating, creating, deleting, pasting, flipping the duplex side, rotating the view, and so on). Call Undo() and Redo() from your UI, and use CanUndo / CanRedo plus the UndoStateChanged event to keep your buttons in sync:

editor.UndoStateChanged += (s, e) =>
{
    undoButton.IsEnabled = editor.CanUndo;
    redoButton.IsEnabled = editor.CanRedo;
};

Undo/Redo also restores which duplex side was active, and items deleted when a duplex document is converted to a simplex one come back with Undo.


View Rotation

RotateView(Rotate) rotates the way the whole label is shown on the surface (Rotate.None, Degree90, Degree180, Degree270), for example to design a label the way it comes out of a printer that feeds it sideways. Items, margins, duplex pages and the background image rotate with the view, and the rulers and grid are updated.

editor.ViewRotationChanged += (s, e) => statusRotation.Text = editor.ViewRotation.ToString();
editor.RotateView(Rotate.Degree90);
  • ViewRotation returns the current rotation.
  • CreateThermalLabel() returns the label as it is currently shown, i.e. with the view rotation applied.
  • Save() and SaveAsJson() store the label un-rotated by default (the label as the user originally designed it). Pass keepViewRotation: true to store it as it is currently shown.
  • RotateLabel(thermalLabel, currentRotation, newRotation) is a helper that rotates any ThermalLabel object without touching the editor.

Duplex Label Design (Front and Back)

A duplex label has a Front and a Back side. The editor shows one side at a time and lets the user flip between them. A duplex design is a LabelDocument with IsDuplexDesign = true and exactly two pages (Pages[0] is the Front, Pages[1] is the Back).

Flipping with Animation

FlipDuplexSide() flips the label with a short "squish" animation. The same flip is available to the user through a button drawn next to the "Front Side" / "Back Side" legend above the label.

editor.ActiveDuplexSideChanged += (s, e) =>
    sideLabel.Text = editor.ActiveDuplexSide == DuplexSide.Front ? "Front" : "Back";

flipButton.Click += (s, e) => editor.FlipDuplexSide();
  • ActiveDuplexSide returns the side currently shown (DuplexSide.Front or DuplexSide.Back).
  • The selection is cleared when the side changes, and Delete All and rubber-band selection only act on the visible side.
  • Both sides share one component tray.
  • The flip is also undoable: Undo/Redo restores the side that was active at that moment.

Moving Items Between Sides

Cut an item on one side, flip, and paste: the item moves to the new side keeping its relative position, and DuplexItemSideChanged is raised with the item, the source side and the target side. Pasting a copy (Copy instead of Cut) always creates the clone on the side being edited.

Out-of-Bounds Validation

The two sides are exported as pages of a single label, so items must stay inside the side they belong to. DuplexOutOfBoundsHandling tells CreateThermalLabel() what to do when an item is outside its side:

DuplexOutOfBoundsPolicy Behavior
RaiseValidationWarning (default) Raises DuplexItemsOutOfBounds. Set e.Cancel = true to abort the export (CreateThermalLabel() then returns null).
MoveOutsideBoundingBox Moves the item outside the global duplex bounding box so it doesn't print on either side, keeping its data.
SetInvisible Keeps the item but sets Visible = false, so it isn't printed.
editor.DuplexItemsOutOfBounds += (s, e) =>
{
    var names = string.Join(", ", e.Items.Select(i => $"{i.Item.Name} ({i.Side})"));
    var answer = MessageBox.Show($"These items are outside their side: {names}. Export anyway?",
                                 "Duplex", MessageBoxButton.YesNo);
    e.Cancel = (answer == MessageBoxResult.No);
};

You can also check at any time with GetDuplexItemsOutOfBounds() (for example, before enabling a Print button). It looks at both sides, not only the visible one.

Switching from Duplex to Simplex

If UpdateLabelDocument() converts a duplex design into a simplex one while the Back side has items, those items would be deleted. BeforeDuplexDesignDisabled fires first so you can ask the user:

editor.BeforeDuplexDesignDisabled += (s, e) =>
{
    var ok = MessageBox.Show($"{e.BackSideItems.Count} item(s) on the Back side will be deleted. Continue?",
                             "Duplex", MessageBoxButton.YesNo) == MessageBoxResult.Yes;
    e.Cancel = !ok;   // Cancel = true: nothing is modified and UpdateLabelDocument() returns false
};

Customizing the Duplex UI

DuplexFlipColor, DuplexFlipHoverColor and DuplexLegendsForeColor change the colors of the flip button and the side legend.


Label Shapes and Backgrounds

  • Round labels: when the LabelDocument has an elliptical shape, the label frame is drawn as an ellipse (a circle when width equals height) and the out-of-label check uses that shape.
  • Design background image: the label's DesignBackgroundImage is shown behind the items on the surface (for example, a scan of a pre-printed label). In duplex designs the image covers the whole Front + gap + Back area and the editor crops out the part that belongs to the visible side.
  • Frame corner radius: LabelDocumentFrameCornerRadius rounds the corners of the label frame and tray.

Item Visual Aids

The editor shows small reference icons on items to tell the user about their state, and a tooltip appears when the pointer is over the item:

Icon / aid Shown when
Data bound The item is bound to a data field
Expression The item contains an expression
Locked The item is locked
Non editable Editable = false
Read only ReadOnly = true
Not visible Visible = false
Comment The item has Comments. The comment text appears as a tooltip when the pointer is over the item.
Print as resident element The item is configured to print as a printer-resident element (and an error variant when it can't)

The item tooltip also shows the item's index. Use RefIconsOpacity to make all these reference icons more or less transparent, and AdornerLegendsVisible to show or hide the text legends of the selection adorners.

Picture missing aid. When an ImageItem's source can't be found, the editor draws a placeholder image instead. Choose it with NoImageFileName.

Picture monochrome preview. The ImageItemUtils class has a method that returns the black & white result of converting an ImageItem's source using that item's MonochromeSettings. Use it to show the user a live preview while they fine-tune those options.


Visual Customization

Almost every color, border, adorner and icon of the editor can be changed so it matches the look of the app that hosts it.

Area What you can customize
Designer background The area around the label (Background)
Rulers Background, lines, foreground (text) and selection highlight colors
Label frame Frame background (solid color or image), frame border, margin area color (LabelDocumentMarginColor) and corner radius
Grid and guides Grid color and type, snap guideline color
Adorners Handle fill, handle hover fill, handle border, selection frame border, rubber-band border and fill, and out-of-label color
Duplex Flip button, flip button hover and legend text colors
Item tooltips Background, border, text and item-index text colors
Component tray Background, border, icon size, gap from the label and the RFID/Literal icons (image file or vector path with its color)
Repeater items The color used to draw RepeaterItem objects
Reference icons Opacity of all the reference icons, and the 12x12 Base64 icon used for each item state (see below)
Strings UpdateBaseOnI18N() refreshes the editor's strings from the current ThermalLabel.I18N object

Property names follow the same pattern in both editions (AdornerHandlerBackColor, GridColor, TrayBackColor, ...). The only differences are the types: WPF uses System.Windows.Media.Color (and a Brush for RulerBackground and LabelDocumentFrameBackground), while Windows Forms uses System.Drawing.Color (and RulerBackColor and LabelDocumentFrameBackColor / LabelDocumentFrameBackgroundImage).

// WPF
editor.AdornerHandlerBackColor  = Colors.White;
editor.AdornerHandlerBorderColor = Colors.DodgerBlue;
editor.AdornerSelectionBorderColor = Colors.DodgerBlue;
editor.GridColor = Color.FromArgb(128, 200, 200, 200);
editor.GuidelineColor = Colors.Magenta;
editor.TrayIconSize = 24;

Global Icon Overrides

The icons used for item states (IconDataBound, IconLocked, IconNonEditable, IconExpression, IconNotVisible, IconComment, IconReadOnly, IconPrintAsResidentElement, IconPrintAsResidentElementError) are static properties holding a 12x12 image as a Base64 string. Because they are static, changing one affects every editor instance in the process.

Saving and Loading a Theme as JSON

All color, image and icon settings can be captured to / applied from JSON, so you can ship the look of your editor as a file, let users pick a skin, or keep several editors consistent. This works the same for WPF and Windows Forms through extension methods in the Neodynamic.Windows.ThermalLabelEditor namespace.

using Neodynamic.Windows.ThermalLabelEditor;

// Save the current look to a file, or get it as a string
editor.SaveAppearanceSettings(@"C:\themes\dark.json");
string json = editor.GetAppearanceSettingsJson();

// Apply a theme from a file or from a string
editor.LoadAppearanceSettings(@"C:\themes\dark.json");
editor.ApplyAppearanceSettingsJson(json);

// Or work with the settings object directly
ThermalLabelEditorAppearanceSettings settings = editor.GetAppearanceSettings();
settings.GridColor = "#80C8C8C8";
editor.ApplyAppearanceSettings(settings);

Things to know about the JSON format:

  • Colors are strings in #AARRGGBB form (#RRGGBB is also accepted and means fully opaque).
  • Partial themes are supported. Only the properties present in the JSON are applied, everything else keeps its current value. A theme file can be as small as:
{
  "AdornerHandlerBackColor": "#FFFFFFFF",
  "AdornerHandlerBorderColor": "#FF1E90FF",
  "GridColor": "#80C8C8C8",
  "TrayIconSize": 24
}
  • The settings include the Icon... static overrides, so applying a theme with those keys changes the icons of every editor in the process.

Events Cheat Sheet

Event Raised when Typical use
LabelLoaded The label is fully loaded on the surface Enable your UI, set the initial zoom
SelectionChanged The selection changes Fill your properties window from CurrentSelection
SelectionAreaChanged The location or size of the selection changes Update X/Y/W/H boxes from CurrentSelectionArea
SelectionItemPropertyChanged A property of the selected item changes (e.IsLiveUpdate tells you if it's part of a drag) Keep the properties window in sync
SelectionTransformStarted / SelectionTransformEnded The user starts / finishes moving, resizing or rotating Do expensive UI refreshes once per gesture
NewItemCreated An item is created (by a tool or by Paste) Show the properties dialog for the new item
CurrentSelectionBeforeDelete The selection is about to be deleted Ask for confirmation (set e.Cancel = true)
CurrentSelectionAfterDelete The selection was deleted Refresh dependent UI
CurrentSelectionTextChanged The text of a TextItem changes while editing Live preview, character counters
UndoStateChanged Undo/Redo availability changes Enable/disable Undo and Redo buttons
ClipboardStateChanged Clipboard availability changes Enable/disable Cut, Copy and Paste buttons
ViewRotationChanged The view rotation changes Update the status bar
ActiveDuplexSideChanged The visible duplex side changes Update the Front/Back indicator
DuplexItemsOutOfBounds CreateThermalLabel() finds items outside their duplex side Warn the user, optionally cancel the export
DuplexItemSideChanged An item moves from one duplex side to the other Log or refresh
BeforeDuplexDesignDisabled A duplex document is about to become simplex while the Back side has items Ask for confirmation

Examples

Properties window that stays responsive while dragging. SelectionItemPropertyChanged can fire many times per second during a drag. The editor throttles those live notifications, but you should still do the heavy work once per gesture:

editor.SelectionChanged += (s, e) => RefreshPropertiesWindow(editor.CurrentSelection);

editor.SelectionItemPropertyChanged += (s, e) =>
{
    if (e.IsLiveUpdate) return;      // skip intermediate updates while dragging
    RefreshPropertiesWindow(editor.CurrentSelection);
};

editor.SelectionTransformEnded += (s, e) => RefreshPropertiesWindow(editor.CurrentSelection);

Confirm before deleting.

editor.CurrentSelectionBeforeDelete += (s, e) =>
{
    e.Cancel = MessageBox.Show("Delete the selected items?", "Confirm",
                               MessageBoxButton.YesNo) == MessageBoxResult.No;
};

Open your properties dialog for each new item.

editor.NewItemCreated += (s, e) => ShowPropertiesDialog(editor.CurrentSelection);

Toolbar state.

editor.ClipboardStateChanged += (s, e) =>
{
    cutButton.IsEnabled   = editor.CanCut;
    copyButton.IsEnabled  = editor.CanCopy;
    pasteButton.IsEnabled = editor.CanPaste;
};

Windows Forms. The WinForms control exposes the same events (and the same duplex event args), so the snippets above work with minimal changes, for example:

labelEditor.DuplexItemsOutOfBounds += (s, e) => { /* same e.Items / e.Cancel */ };
labelEditor.SelectionChanged += (s, e) => RefreshPropertiesWindow(labelEditor.CurrentSelection);

Features at a Glance

  • Rulers: top and left rulers that follow the label's unit and show the selection extent; colors are customizable.
  • Items' selection and handlers: rubber-band selection, click, CTRL + click, move/resize/rotate handlers, keyboard movement.
  • Keyboard-based item movement: arrow keys for small steps, CTRL + arrow keys for long steps.
  • In-place text edition: double-click or F2, also on rotated text items.
  • Picture missing aid and picture monochrome preview for ImageItem objects.
  • Items' comments: tooltip shown when the pointer is over an item that has Comments.
  • High quality zoom: 10% to 1000%, plus zoom-to-fit.
  • Undo/Redo and Cut-Copy-Paste (internal or system clipboard).
  • Z-ordering, grouping, alignment, distribution and same size tools.
  • Grid lines or dots, snap to grid, snap to nearby items with guide lines, angle snap.
  • Locking items so they can't be moved accidentally.
  • View rotation in 90-degree steps.
  • Duplex (Front/Back) design with flip animation and out-of-bounds validation.
  • Round labels, design background image, component tray for RFID tags and literals.
  • Full visual customization with JSON themes.
  • WPF routed commands for declarative UI binding.

Breaking Changes (from versions 4.0 to 7.0)

  • The BarcodeItemUtils class moved to the Neodynamic.SDK.ThermalLabel.dll assembly.

Migrating to ThermalLabelEditor v16

If you're using an older version of ThermalLabelWebEditor (4.0 to 7.0), follow these steps to migrate to Version 16.0:

  • v16 requires .NET Framework 4.6.1+ or .NET Core 3.1+ (older .NET versions are no longer supported).
  • v16 requires your project to reference the following NuGet packages:
    • SkiaSharp 1.68.3+
    • System.Text.Encoding.CodePages 4.4.0+
  • Any .NET project using the new Windows Editor v16 must reference the new Neodynamic.SDK.ThermalLabel.WindowsPrinting.dll assembly and the new Neodynamic.SDK.ThermalLabel.dll assembly.
Back to top Copyright © 2003- Neodynamic SRL
http://www.neodynamic.com