A ProEssentials v11 WinUI 3 .NET 10 demonstration combining two PesgoWinUI
features: custom PNG bitmap symbols as data point markers, and jagged data
where each subset has a different number of points.
| Subset | Points | Symbol | Strategy |
|---|---|---|---|
| 0 | 12,000 | symbolBlueDot.png |
ColorizeMode=None — pre-colored, renders native colors |
| 1 | 1,200 | symbol01.png |
ColorizeMode=Mask — silhouette tinted cyan by SubsetColors |
| 2 | 120 | symbol02.png |
ColorizeMode=Mask — silhouette tinted gold by SubsetColors |
| 3 | 12 | symbol03.png |
ColorizeMode=Mask — silhouette tinted red by SubsetColors |
Place these PNG files in the same folder as the built executable:
symbolBlueDot.png — pre-colored blue dot (ColorizeMode=None)
symbol01.png — dark silhouette on transparent background (ColorizeMode=Mask)
symbol02.png — dark silhouette on transparent background (ColorizeMode=Mask)
symbol03.png — dark silhouette on transparent background (ColorizeMode=Mask)
They are in the repository root and the .csproj copies them to the output
directory on build.
Each WorkingBitmap slot holds one PNG file. Subsets reference slots via:
SubsetPointTypes[s] = (PointType)(10001 + workingBitmapIndex);Standard PointType enum values stay below 100. Values ≥ 10001 are
interpreted as bitmap resource slot references by the engine.
ColorizeMode = None — Pre-colored bitmap:
Pesgo1.PePlot.Bitmaps.WorkingBitmap = 0;
Pesgo1.PePlot.Bitmaps.Filename = "symbolBlueDot.png";
Pesgo1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.None; // render native colors
Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.MediumCentered;The bitmap renders exactly as stored. Used for pre-colored images (blue dot,
3D sphere renders, complex icons) where tinting would look wrong. The subset's
SubsetColors entry only affects the legend color swatch, not the symbol.
ColorizeMode = Mask — Silhouette tinted by SubsetColors:
Pesgo1.PePlot.Bitmaps.WorkingBitmap = 1;
Pesgo1.PePlot.Bitmaps.Filename = "symbol01.png"; // dark shape on transparent bg
Pesgo1.PePlot.Bitmaps.ColorizeMode = ResourceBitmapColorizeMode.Mask; // tinted by SubsetColors[1]
Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.MediumCentered;The bitmap source should be a dark shape on a transparent background.
ProEssentials tints it using the subset's SubsetColors entry. One PNG
file produces any color — one shape, unlimited color variants.
var bitmaps = new (int slot, string file, ResourceBitmapColorizeMode colorize)[]
{
(0, "symbolBlueDot.png", ResourceBitmapColorizeMode.None),
(1, "symbol01.png", ResourceBitmapColorizeMode.Mask),
(2, "symbol02.png", ResourceBitmapColorizeMode.Mask),
(3, "symbol03.png", ResourceBitmapColorizeMode.Mask),
};
foreach (var (slot, file, colorize) in bitmaps)
{
Pesgo1.PePlot.Bitmaps.WorkingBitmap = slot;
Pesgo1.PePlot.Bitmaps.Filename = file;
Pesgo1.PePlot.Bitmaps.ColorizeMode = colorize;
Pesgo1.PePlot.Bitmaps.Style = ResourceBitmapStyle.MediumCentered;
}Bitmap resource symbols cannot be represented in pure vector format. Disable WMF and EMF export when using them:
Pesgo1.PeUserInterface.Dialog.AllowWmfExport = false;
Pesgo1.PeUserInterface.Dialog.AllowEmfExport = false;PNG export works correctly at any resolution.
JaggedData = true allows each subset to have an independent point count:
Pesgo1.PeData.JaggedData = true;
Pesgo1.PeData.Subsets = 4;
Pesgo1.PeData.Points = 1; // auto-adjusts to max subset count on reinitializeIMPORTANT: JaggedData requires RenderEngine = Direct2D. Direct3D does
not support the per-subset variable point count architecture.
Setting the last element of each subset before the data loop prevents incremental internal reallocations:
Pesgo1.PeData.X[0, 11999] = 0f; Pesgo1.PeData.Y[0, 11999] = 0f;
Pesgo1.PeData.X[1, 1199] = 0f; Pesgo1.PeData.Y[1, 1199] = 0f;
// ...This is the validated .NET pre-allocation pattern. SetJaggedPointsX/Y
exist only in the OCX/VBA API, not in .NET.
Build a float[] array per subset, then copy in one call:
float[] xData = new float[count];
float[] yData = new float[count];
for (int p = 0; p < count; p++)
{
xData[p] = (p + 1) * stepX;
yData[p] = /* ... */;
}
Pesgo1.PeData.X.FastCopyFromJagged(xData, subsetIndex);
Pesgo1.PeData.Y.FastCopyFromJagged(yData, subsetIndex);FastCopyFromJagged(source, subsetIndex) performs a single memcpy into
that subset and sets its size from the source array length. This is
significantly faster than spoon-feeding Y[s,p] element by element for
large point counts, and produces cleaner, more readable code.
| Input | Action |
|---|---|
| Left-click drag | Zoom box |
| Mouse wheel | Zoom both axes |
| Right-click | Context menu — PNG export, print, customize |
The chart-configuration code above is identical to the WPF version of this example. The ProEssentials API does not change between interfaces; only the window plumbing differs.
No XAML designer — Visual Studio has no XAML designer for WinUI 3, in any
edition including VS2026. The chart is declared in markup
(<pe:PesgoWinUI x:Name="Pesgo1" />) rather than dragged from the Toolbox.
This is a Windows App SDK limitation, not a ProEssentials one.
Window sizing is code, not XAML — a WinUI Window is not a Control. It
has no Height/Width/MinWidth in XAML, no Loaded event and no
Background. SizeAndCenterWindow() sets the size with a Win32 MoveWindow
call, and the window background moves to the root Grid.
Control Loaded event — ProEssentials initialization happens in the chart's
own Loaded event (Pesgo1_Loaded), never at window level.
- Visual Studio 2026 with the .NET desktop development and Windows application development workloads
- .NET 10 SDK
- Bitmap PNG files in the executable output directory
1. Clone this repository
2. symbolBlueDot.png, symbol01.png, symbol02.png and symbol03.png live in the
project root and are copied to the output on build (or place them directly
in bin\x64\Debug\net10.0-windows10.0.19041.0\)
3. Open BitmapSymbolsJaggedData.sln in Visual Studio 2026
4. Build → Rebuild Solution (NuGet restore is automatic)
5. Press F5
References
ProEssentials.Chart.Net10.WinUI.
Package restore is automatic on build.
The AnyCpu package embeds the native rendering engines inside the assembly and unpacks the one matching the running process at run time, so there is no native DLL to copy or deploy alongside your app.
WinUI deploys differently than WPF and WinForms — worth knowing before you ship:
- A .NET app is not a single exe. Ship the entire build/publish output folder, never a hand-picked subset.
- The target machine needs two runtimes: the .NET 10 Desktop Runtime and the Windows App SDK Runtime. Alternatively publish self-contained with
-p:WindowsAppSDKSelfContained=true. - Your development machine already has both, so it will run from an under-filled folder. Always validate on a clean machine.
- The four symbol PNGs must travel with the app folder; the engine loads them by filename at run time.
The nuget.org package is the evaluation build and draws an "Evaluating ProEssentials" watermark across the chart. A licensed installation replaces the assembly and the watermark goes away — everything else behaves identically.
- WPF version of this example
- All Examples — GigasoftInc on GitHub
- Full Evaluation Download
- gigasoft.com
Example code is MIT licensed. ProEssentials requires a commercial license for continued use.
