Migrating from Infragistics Barcode to IronBarcode
Most Infragistics barcode migrations happen because the team needed barcode reading in a project where only generation was available - WinForms, ASP.NET Core, or any project outside WPF - or because the event-driven WPF reader API proved too brittle for production use. The TaskCompletionSource bridge pattern, the shared _result field that makes concurrent calls unsafe, and the silent failures from missing SymbologyType flags are all common reasons teams look for an alternative.
This guide walks through the full migration: removing Infragistics barcode packages, replacing generation and reading code in both WinForms and WPF contexts, and adding barcode functionality to project types where Infragistics had no support at all.
Quick Start
Step 1: Remove Infragistics Barcode Packages
Remove the Infragistics barcode NuGet packages from your project. Depending on which targets you were using:
# WinForms generation package
dotnet remove package Infragistics.WinForms.Barcode
# WPF reading package
dotnet remove package Infragistics.WPF.BarcodeReader
If your project file references both, remove both. The Infragistics Ultimate license is not affected by removing barcode-specific packages if you have other Infragistics components in use.
Step 2: Install IronBarcode
dotnet add package IronBarcode
IronBarcode is a single package that works across WinForms, WPF, ASP.NET Core, console, Blazor Server, Docker, Azure Functions, and AWS Lambda. You do not need separate packages per framework.
Step 3: Update Namespaces
Replace Infragistics barcode namespaces with IronBarCode (capital B, capital C):
// Remove these:
// using Infragistics.Win.UltraWinBarcode;
// using Infragistics.Controls.Barcodes;
// using System.Windows.Media.Imaging; // if only used for barcode BitmapImage loading
// Add this:
using IronBarCode;Imports IronBarCodeStep 4: Initialize the License
Add license initialization once at application startup - Program.cs, App.xaml.cs, or your DI composition root:
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY";Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR-LICENSE-KEY"Code Migration Examples
WinForms Generation: UltraWinBarcode to BarcodeWriter
The WinForms generation pattern maps cleanly to IronBarcode's BarcodeWriter:
Before (Infragistics WinForms):
using Infragistics.Win.UltraWinBarcode;
var barcode = new UltraWinBarcode();
barcode.Symbology = Symbology.Code128;
barcode.Data = "ITEM-12345";
barcode.SaveTo(outputPath);Imports Infragistics.Win.UltraWinBarcode
Dim barcode As New UltraWinBarcode()
barcode.Symbology = Symbology.Code128
barcode.Data = "ITEM-12345"
barcode.SaveTo(outputPath)After (IronBarcode):
// NuGet: dotnet add package IronBarcode
using IronBarCode;
BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
.SaveAsPng(outputPath);Imports IronBarCode
BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128) _
.SaveAsPng(outputPath)The Infragistics Symbology enum value moves to the BarcodeEncoding enum, which is a parameter to CreateBarcode() rather than a property assignment. The data becomes the first argument. SaveTo() becomes .SaveAsPng(), .SaveAsJpeg(), .SaveAsSvg(), or .SaveAsPdf() depending on your output format.
If you need to resize the barcode before saving:
using IronBarCode;
BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128)
.ResizeTo(400, 100)
.SaveAsPng(outputPath);Imports IronBarCode
BarcodeWriter.CreateBarcode("ITEM-12345", BarcodeEncoding.Code128) _
.ResizeTo(400, 100) _
.SaveAsPng(outputPath)WPF Event-Driven Reading: Service Class to Two Lines
This is the most significant reduction in the migration. The Infragistics WPF reading pattern requires a full service class:
Before (Infragistics WPF - ~35 lines):
using Infragistics.Controls.Barcodes;
using System.Windows.Media.Imaging;
private BarcodeReader _reader;
private TaskCompletionSource<string> _result;
public InfragisticsBarcodeService()
{
_reader = new BarcodeReader();
_reader.DecodeComplete += OnDecodeComplete;
}
public async Task<string> ReadBarcodeAsync(string imagePath)
{
_result = new TaskCompletionSource<string>();
var bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute));
_reader.SymbologyTypes = Symbology.Code128 |
Symbology.Code39 |
Symbology.QRCode |
Symbology.EAN8 |
Symbology.EAN13 |
Symbology.UpcA |
Symbology.Interleaved2Of5;
_reader.Decode(bitmap);
return await _result.Task;
}
private void OnDecodeComplete(object sender, ReaderDecodeArgs e)
{
_result?.TrySetResult(e.Value ?? "No barcode found");
}
public void Dispose()
{
if (_reader != null)
{
_reader.DecodeComplete -= OnDecodeComplete;
_reader = null;
}
}Imports Infragistics.Controls.Barcodes
Imports System.Windows.Media.Imaging
Imports System.Threading.Tasks
Private _reader As BarcodeReader
Private _result As TaskCompletionSource(Of String)
Public Sub New()
_reader = New BarcodeReader()
AddHandler _reader.DecodeComplete, AddressOf OnDecodeComplete
End Sub
Public Async Function ReadBarcodeAsync(imagePath As String) As Task(Of String)
_result = New TaskCompletionSource(Of String)()
Dim bitmap As New BitmapImage(New Uri(imagePath, UriKind.Absolute))
_reader.SymbologyTypes = Symbology.Code128 Or
Symbology.Code39 Or
Symbology.QRCode Or
Symbology.EAN8 Or
Symbology.EAN13 Or
Symbology.UpcA Or
Symbology.Interleaved2Of5
_reader.Decode(bitmap)
Return Await _result.Task
End Function
Private Sub OnDecodeComplete(sender As Object, e As ReaderDecodeArgs)
_result?.TrySetResult(If(e.Value, "No barcode found"))
End Sub
Public Sub Dispose()
If _reader IsNot Nothing Then
RemoveHandler _reader.DecodeComplete, AddressOf OnDecodeComplete
_reader = Nothing
End If
End SubAfter (IronBarcode - 2 lines):
using IronBarCode;
var results = BarcodeReader.Read(imagePath);
return results.FirstOrDefault()?.Value ?? "No barcode found";Imports IronBarCode
Dim results = BarcodeReader.Read(imagePath)
Return If(results.FirstOrDefault()?.Value, "No barcode found")The entire service class - instance management, event wiring, TaskCompletionSource, BitmapImage loading, Dispose() - is gone. BarcodeReader.Read() is synchronous, static, and accepts a file path string directly.
If you were returning the symbology type as well:
using IronBarCode;
var results = BarcodeReader.Read(imagePath);
var first = results.FirstOrDefault();
if (first != null)
{
Console.WriteLine($"Value: {first.Value}, Format: {first.Format}");
}Imports IronBarCode
Dim results = BarcodeReader.Read(imagePath)
Dim first = results.FirstOrDefault()
If first IsNot Nothing Then
Console.WriteLine($"Value: {first.Value}, Format: {first.Format}")
End Ifresult.Value replaces e.Value. result.Format replaces e.Symbology.
Adding WinForms Reading (Previously Impossible)
If you were in a WinForms project that only had generation, reading is now available with the same package:
using IronBarCode;
// In a WinForms button handler or service method — same API as WPF or ASP.NET Core
var results = BarcodeReader.Read(imagePath);
foreach (var result in results)
{
MessageBox.Show($"Found: {result.Value} ({result.Format})");
}Imports IronBarCode
' In a WinForms button handler or service method — same API as WPF or ASP.NET Core
Dim results = BarcodeReader.Read(imagePath)
For Each result In results
MessageBox.Show($"Found: {result.Value} ({result.Format})")
NextNo additional packages, no framework-specific setup. The same BarcodeReader.Read() call works in WinForms as in WPF.
ASP.NET Core Endpoint (Previously Impossible)
Barcode generation and reading in an ASP.NET Core controller was not possible with Infragistics packages. With IronBarcode:
using IronBarCode;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/barcode")]
public class BarcodeController : ControllerBase
{
[HttpPost("read")]
public IActionResult ReadBarcode(IFormFile imageFile)
{
using var stream = imageFile.OpenReadStream();
var results = BarcodeReader.Read(stream);
var values = results.Select(r => new { r.Value, Format = r.Format.ToString() });
return Ok(values);
}
[HttpGet("generate")]
public IActionResult GenerateBarcode([FromQuery] string data)
{
var bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128)
.ResizeTo(400, 100)
.ToPngBinaryData();
return File(bytes, "image/png");
}
}Imports IronBarCode
Imports Microsoft.AspNetCore.Mvc
<ApiController>
<Route("api/barcode")>
Public Class BarcodeController
Inherits ControllerBase
<HttpPost("read")>
Public Function ReadBarcode(imageFile As IFormFile) As IActionResult
Using stream = imageFile.OpenReadStream()
Dim results = BarcodeReader.Read(stream)
Dim values = results.Select(Function(r) New With {Key .Value = r.Value, Key .Format = r.Format.ToString()})
Return Ok(values)
End Using
End Function
<HttpGet("generate")>
Public Function GenerateBarcode(<FromQuery> data As String) As IActionResult
Dim bytes = BarcodeWriter.CreateBarcode(data, BarcodeEncoding.Code128) _
.ResizeTo(400, 100) _
.ToPngBinaryData()
Return File(bytes, "image/png")
End Function
End ClassBarcodeReader.Read() accepts a Stream directly - no need to save the upload to disk first.
PDF Barcode Reading
IronBarcode reads barcodes from PDF documents natively - no separate package required:
using IronBarCode;
// Read all barcodes from every page of a PDF
var results = BarcodeReader.Read("document.pdf");
foreach (var result in results)
{
Console.WriteLine($"Page {result.PageNumber}: {result.Value} ({result.Format})");
}Imports IronBarCode
' Read all barcodes from every page of a PDF
Dim results = BarcodeReader.Read("document.pdf")
For Each result In results
Console.WriteLine($"Page {result.PageNumber}: {result.Value} ({result.Format})")
NextInfragistics had no equivalent - PDF barcode reading required converting PDF pages to images externally before scanning.
Batch Processing: Sequential to Parallel
Before (Infragistics - sequential, not concurrency-safe for parallelization):
// Must process one at a time — shared _result field is not thread-safe
var service = new InfragisticsBarcodeService();
var results = new List<string>();
foreach (var file in imageFiles)
{
var value = await service.ReadBarcodeAsync(file);
results.Add(value);
}
service.Dispose();Imports System.Collections.Generic
' Must process one at a time — shared _result field is not thread-safe
Dim service As New InfragisticsBarcodeService()
Dim results As New List(Of String)()
For Each file In imageFiles
Dim value As String = Await service.ReadBarcodeAsync(file)
results.Add(value)
Next
service.Dispose()After (IronBarcode - parallel, thread-safe):
using IronBarCode;
// Option 1: pass an array directly — IronBarcode handles parallelization internally
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = true,
MaxParallelThreads = 4
};
var results = BarcodeReader.Read(imageFiles.ToArray(), options);
foreach (var result in results)
{
Console.WriteLine($"{result.Value} ({result.Format})");
}Imports IronBarCode
' Option 1: pass an array directly — IronBarcode handles parallelization internally
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = True,
.MaxParallelThreads = 4
}
Dim results = BarcodeReader.Read(imageFiles.ToArray(), options)
For Each result In results
Console.WriteLine($"{result.Value} ({result.Format})")
Nextusing IronBarCode;
using System.Collections.Concurrent;
// Option 2: Parallel.ForEach — static BarcodeReader.Read is thread-safe
var allValues = new ConcurrentBag<string>();
Parallel.ForEach(imageFiles, file =>
{
var results = BarcodeReader.Read(file);
foreach (var r in results)
allValues.Add(r.Value);
});Imports IronBarCode
Imports System.Collections.Concurrent
' Option 2: Parallel.ForEach — static BarcodeReader.Read is thread-safe
Dim allValues As New ConcurrentBag(Of String)()
Parallel.ForEach(imageFiles, Sub(file)
Dim results = BarcodeReader.Read(file)
For Each r In results
allValues.Add(r.Value)
Next
End Sub)Removing the Dispose Pattern
If your code had IDisposable implementations around the Infragistics BarcodeReader, those can be removed entirely. IronBarcode's BarcodeReader is a static class. There is no instance to create, no event handler to detach, and no Dispose() to call.
// Before: service registered as IDisposable in DI container
services.AddScoped<InfragisticsBarcodeService>(); // implements IDisposable
// After: no registration needed — use static method directly, or wrap in thin service if preferred
// services.AddScoped<IBarcodeService, IronBarcodeService>();' Before: service registered as IDisposable in DI container
services.AddScoped(Of InfragisticsBarcodeService)() ' implements IDisposable
' After: no registration needed — use static method directly, or wrap in thin service if preferred
' services.AddScoped(Of IBarcodeService, IronBarcodeService)()A thin wrapper service for DI purposes is straightforward:
using IronBarCode;
public class BarcodeService
{
public IEnumerable<string> Read(string path)
=> BarcodeReader.Read(path).Select(r => r.Value);
public byte[] Generate(string data, BarcodeEncoding encoding)
=> BarcodeWriter.CreateBarcode(data, encoding).ToPngBinaryData();
}Imports IronBarCode
Public Class BarcodeService
Public Function Read(path As String) As IEnumerable(Of String)
Return BarcodeReader.Read(path).Select(Function(r) r.Value)
End Function
Public Function Generate(data As String, encoding As BarcodeEncoding) As Byte()
Return BarcodeWriter.CreateBarcode(data, encoding).ToPngBinaryData()
End Function
End ClassNo constructor injection, no Dispose(), no event management.
Common Migration Issues
SymbologyType Flags Removed
The SymbologyTypes property on the Infragistics WPF reader required you to enumerate every barcode format you wanted to support. IronBarcode has no equivalent - it auto-detects all 50+ supported formats on every read.
This has an important side effect: if a particular barcode format was silently failing before because its SymbologyType flag was missing from the list, IronBarcode will now find it. You may see barcode values appearing in production that were previously being swallowed silently. This is the correct behavior - those barcodes were always there.
If you need to constrain which formats are returned (for performance or ambiguity reasons), BarcodeReaderOptions supports this:
using IronBarCode;
var options = new BarcodeReaderOptions
{
Speed = ReadingSpeed.Balanced,
ExpectMultipleBarcodes = false
};
var results = BarcodeReader.Read(imagePath, options);Imports IronBarCode
Dim options As New BarcodeReaderOptions With {
.Speed = ReadingSpeed.Balanced,
.ExpectMultipleBarcodes = False
}
Dim results = BarcodeReader.Read(imagePath, options)BitmapImage Loading Not Needed
The Infragistics WPF reader required loading images as BitmapSource objects via new BitmapImage(new Uri(path, UriKind.Absolute)). IronBarcode accepts file path strings, byte arrays, and streams directly:
// All of these work — no BitmapImage conversion needed
BarcodeReader.Read("path/to/image.png");
BarcodeReader.Read(File.ReadAllBytes("path/to/image.png"));
BarcodeReader.Read(File.OpenRead("path/to/image.png"));' All of these work — no BitmapImage conversion needed
BarcodeReader.Read("path/to/image.png")
BarcodeReader.Read(File.ReadAllBytes("path/to/image.png"))
BarcodeReader.Read(File.OpenRead("path/to/image.png"))You can remove any using System.Windows.Media.Imaging; imports that were only there for barcode-related image loading.
TaskCompletionSource Pattern Removed
The TaskCompletionSource<string> field that bridged the event-driven DecodeComplete callback into async code is gone entirely. BarcodeReader.Read() is synchronous and returns its results directly.
If your calling code was await service.ReadBarcodeAsync(path), you can simplify to:
// Before
var value = await service.ReadBarcodeAsync(imagePath);
// After
var value = BarcodeReader.Read(imagePath).FirstOrDefault()?.Value ?? "No barcode found";netIf you want to preserve an async interface for downstream callers without blocking a thread:
public Task<string> ReadBarcodeAsync(string imagePath)
{
return Task.Run(() =>
{
var results = BarcodeReader.Read(imagePath);
return results.FirstOrDefault()?.Value ?? "No barcode found";
});
}Option Strict On
Option Infer On
Public Function ReadBarcodeAsync(imagePath As String) As Task(Of String)
Return Task.Run(Function()
Dim results = BarcodeReader.Read(imagePath)
Return If(results.FirstOrDefault()?.Value, "No barcode found")
End Function)
End FunctionProperty Name Changes
| Infragistics | IronBarcode |
|---|---|
e.Value (in ReaderDecodeArgs) | result.Value |
e.Symbology (in ReaderDecodeArgs) | result.Format |
barcode.Data | First argument of BarcodeWriter.CreateBarcode() |
barcode.Symbology = Symbology.Code128 | BarcodeEncoding.Code128 (parameter) |
barcode.SaveTo(path) | .SaveAsPng(path) / .SaveAsJpeg(path) / .SaveAsSvg(path) |
Migration Checklist
Use these grep patterns to find all Infragistics barcode usage in your codebase:
# Namespace references
grep -r "Infragistics.WinForms.Barcode\|Infragistics.Win.UltraWinBarcode" --include="*.cs" .
grep -r "Infragistics.Controls.Barcodes" --include="*.cs" .
grep -r "Infragistics.WPF.BarcodeReader" --include="*.csproj" .
# WinForms generation types
grep -r "UltraWinBarcode" --include="*.cs" .
grep -r "Symbology\.Code" --include="*.cs" .
grep -r "barcode\.SaveTo(" --include="*.cs" .
# WPF reading types and patterns
grep -r "new BarcodeReader()" --include="*.cs" .
grep -r "DecodeComplete" --include="*.cs" .
grep -r "ReaderDecodeArgs" --include="*.cs" .
grep -r "SymbologyType\." --include="*.cs" .
grep -r "e\.Value\|ReaderDecodeArgs" --include="*.cs" .
grep -r "BitmapImage" --include="*.cs" .
# TaskCompletionSource usage (likely barcode-related if near above patterns)
grep -r "TaskCompletionSource" --include="*.cs" .
Work through each match:
UltraWinBarcodeusages: replace withBarcodeWriter.CreateBarcode()new BarcodeReader()+DecodeCompleteblocks: replace withBarcodeReader.Read()SymbologyTypeflag lists: delete entirelyBitmapImageloads used for barcode input: replace with direct path/stream/bytesReaderDecodeArgs ecallback bodies: extracte.Value→result.Value,e.Symbology→result.FormatIDisposableon barcode service classes: remove if the only disposable resource was_reader
Feature Comparison
| Feature | Infragistics Barcode | IronBarcode |
|---|---|---|
| WinForms barcode generation | Yes (UltraWinBarcode) | Yes |
| WinForms barcode reading | Not available | Yes |
| WPF barcode generation | Yes (XamBarcode) | Yes |
| WPF barcode reading | Yes (event-driven) | Yes (synchronous) |
| ASP.NET Core | Not available | Yes |
| Console / Worker Service | Not available | Yes |
| Docker / Linux | Not available | Yes |
| Azure Functions | Not available | Yes |
| Blazor Server | Not available | Yes |
| Auto format detection | No - SymbologyType flags required | Yes |
| PDF barcode reading | Not available | Yes (native) |
| Thread-safe concurrent reads | No | Yes |
| Batch reading (built-in) | No | Yes |
| QR error correction control | Not available | Yes |
| Static API (no instance) | No | Yes |
| Suite subscription required | Yes (Infragistics Ultimate, $2,399+/year) | No |
| Perpetual license | No | Yes - from $999 |
Key Benefits After Migration
Barcode reading in WinForms. If the migration was driven by a WinForms reading requirement, this is the primary outcome: BarcodeReader.Read(imagePath) compiles and runs in WinForms with no additional setup.
ASP.NET Core and console support. Web APIs, background services, and console tools can now both generate and read barcodes using the same package. If you were maintaining separate tool chains or workarounds for these project types, they are gone.
No event handler boilerplate. The DecodeComplete handler, the TaskCompletionSource bridge, the BitmapImage load, and the Dispose() cleanup are all removed. The barcode logic is what remains.
No symbology specification. Formats that were silently failing due to missing SymbologyType flags will now be detected correctly. Auto-detection covers all 50+ formats without configuration.
Same service class across all project types. A single BarcodeService wrapper using BarcodeReader.Read() and BarcodeWriter.CreateBarcode() can be shared across WinForms, WPF, ASP.NET Core, and any other project in the solution. No framework-specific implementations.
No Infragistics Ultimate subscription required for barcode functionality alone. If barcode support was the only reason your project had an Infragistics Ultimate subscription, or if it was a significant factor in the decision, IronBarcode is a standalone package with perpetual licensing options starting at $999 for a single developer.
The migration itself is mechanical once you have located all the Infragistics barcode usage. The most involved part is the WPF service class replacement, and even that reduces to removing the class and replacing calls with BarcodeReader.Read(). The generation migration is a one-to-one property/method rename. What you get back is a single, consistent API that works in every project type you need.

Curtis Chau holds a Bachelor’s degree in Computer Science (Carleton University) and specializes in front-end development with expertise in Node.js, TypeScript, JavaScript, and React. Passionate about crafting intuitive and aesthetically pleasing user interfaces, Curtis enjoys working with modern frameworks and creating well-structured, visually appealing manuals.