A ProEssentials v11 WinUI 3 .NET 10 demonstration of two distinct approaches
to replacing the default numeric Y-axis labels with custom text — shown
side-by-side in a single PesgoWinUI chart split into two stacked
multi-axis sections.
A single PesgoWinUI chart with two independent Y-axis sections, each
using a different technique to display custom Y-axis labels:
| Section | Approach | Best For |
|---|---|---|
| Top | Line Annotation Grid Lines | Fixed labels known at design time |
| Bottom | PeCustomGridNumber Event |
Dynamic labels — works after zoom/scroll |
The chart-configuration code is identical to the WPF version of this example. The ProEssentials API does not change between interfaces; only the window plumbing differs.
Two subsets share one chart but each gets its own independent Y-axis
section via MultiAxesSubsets:
Pesgo1.PeGrid.MultiAxesSubsets[0] = 1; // top section — subset 0
Pesgo1.PeGrid.MultiAxesSubsets[1] = 1; // bottom section — subset 1
Pesgo1.PeGrid.MultiAxesProportions[0] = 0.5f;
Pesgo1.PeGrid.MultiAxesProportions[1] = 0.5f;
Pesgo1.PeGrid.Option.MultiAxisStyle = MultiAxisStyle.SeparateAxes;
Pesgo1.PeGrid.Option.MultiAxesSeparators = MultiAxesSeparators.Medium;
// End-user can drag the separator to resize sections
Pesgo1.PeUserInterface.Allow.MultiAxesSizing = true;WorkingAxis selects which axis subsequent property assignments apply to.
Always reset to 0 when finished configuring axes.
The default numeric Y scale is hidden and replaced by LineAnnotationType.GridLine
and GridTick annotations:
Pesgo1.PeGrid.WorkingAxis = 0;
// Hide the default numeric scale
Pesgo1.PeGrid.Option.ShowYAxis = ShowAxis.Empty;
// Fix the range so annotation values land at meaningful positions
Pesgo1.PeGrid.Configure.ManualScaleControlY = ManualScaleControl.MinMax;
Pesgo1.PeGrid.Configure.ManualMinY = 0.0;
Pesgo1.PeGrid.Configure.ManualMaxY = 1500.0;
// Annotations targeted to axis 0 via YAxisAxis[i]
Pesgo1.PeAnnotation.Line.YAxisAxis[0] = 0;
Pesgo1.PeAnnotation.Line.YAxis[0] = 200;
Pesgo1.PeAnnotation.Line.YAxisType[0] = LineAnnotationType.GridLine;
Pesgo1.PeAnnotation.Line.YAxisText[0] = "|LLow Value";
// ... more GridLine and GridTick entries ...
Pesgo1.PeAnnotation.Line.LeftMargin = "Medium Value "; // longest label
Pesgo1.PeAnnotation.Show = true;
Pesgo1.PeFont.LineAnnotationTextSize = 100;YAxisAxis[i] = 0 is what makes annotations appear only in the top
axis region. Without it, annotations default to axis 0, but setting it
explicitly is required for multi-axis correctness and clarity.
GridTick adds intermediate tick marks without a label — useful for
subdividing the range between labeled gridlines.
Trade-off: label values must be known at design time. If the user zooms, new intermediate values appear as unlabeled numbers.
CustomGridNumbersY = true is set while WorkingAxis = 1 so it applies
only to the bottom axis:
Pesgo1.PeGrid.WorkingAxis = 1;
Pesgo1.PeGrid.Option.CustomGridNumbersY = true;The PeCustomGridNumber event fires for each grid line during image
construction. The handler checks e.AxisIndex (1 = bottom axis) and
e.AxisType (0 = left Y) before rewriting e.NumberString:
private void Pesgo1_PeCustomGridNumber(object sender,
Gigasoft.ProEssentials.EventArg.CustomGridNumberEventArgs e)
{
if (e.AxisIndex != 1 || e.AxisType != 0) return;
int level = (int)Math.Round(Math.Abs(e.NumberValue));
e.NumberString = e.NumberValue >= 0
? $"+ {level}"
: $"− {level}";
}WinUI has no XAML designer, so the event is wired in the constructor rather than from a XAML attribute:
Pesgo1.Loaded += new RoutedEventHandler(Pesgo1_Loaded);
Pesgo1.PeCustomGridNumber += Pesgo1_PeCustomGridNumber;Trade-off: slightly more code, but works correctly after any zoom or scroll because the event fires fresh for whatever values appear on screen.
Warning: do not place breakpoints inside this event handler. It fires during image construction; a breakpoint can trigger a recursive paint. Use
Debug.WriteLineor trace logging instead.
Axis label and grid number colors are synced to subset data colors so the
user can visually associate each Y axis with its data line. WinUI uses
Windows.UI.Color where WPF used System.Windows.Media.Color — same
FromArgb(a, r, g, b) signature:
Pesgo1.PeGrid.WorkingAxis = 0;
Pesgo1.PeColor.YAxis = ColorTop; // cyan
Pesgo1.PeColor.SubsetColors[0] = ColorTop;
Pesgo1.PeGrid.WorkingAxis = 1;
Pesgo1.PeColor.YAxis = ColorBottom; // orange
Pesgo1.PeColor.SubsetColors[1] = ColorBottom;| Input | Action |
|---|---|
| Left-click drag | Zoom box |
| Drag separator | Resize top / bottom sections |
| Right-click | Context menu — export, print, customize |
- Visual Studio 2026 with the .NET desktop development and Windows application development workloads
- .NET 10 SDK
- Internet connection for NuGet restore
No XAML designer: Visual Studio has no XAML designer for WinUI 3 in any edition, so the chart is declared in markup (
<pe:PesgoWinUI x:Name="Pesgo1" />) rather than dragged from the Toolbox. That is a Windows App SDK limitation, not a ProEssentials one. Nothing needs to be installed beyond the NuGet packages for this project to build and run.
Two more WinUI window differences show up in this sample: a WinUI Window
is not a Control, so it has no XAML Height/Width (the size is set with
SizeAndCenterWindow() in the constructor) and no Loaded event — chart
initialization runs from the chart's own Loaded, which is where it belongs
in every interface anyway.
1. Clone this repository
2. Open CustomYAxisLabelingWinUI.sln in Visual Studio 2026
3. Build → Rebuild Solution (restores NuGet packages automatically)
4. 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. It also carries the control's .pri,
whose resources are merged into your app's own .pri at build 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.
WinUI deploys differently than WPF and WinForms:
- A .NET app is not a single exe — ship the entire build or 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. Or 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.
- WPF version — wpf-chart-custom-yaxis-labels-annotations-events-proessentials
- All Examples — GigasoftInc on GitHub
- Full Evaluation Download
- gigasoft.com
Example code is MIT licensed. ProEssentials requires a commercial license for continued use.
