ArionUI.Rendering.Skia
0.1.0-preview.1
Prefix Reserved
dotnet add package ArionUI.Rendering.Skia --version 0.1.0-preview.1
NuGet\Install-Package ArionUI.Rendering.Skia -Version 0.1.0-preview.1
<PackageReference Include="ArionUI.Rendering.Skia" Version="0.1.0-preview.1" />
<PackageVersion Include="ArionUI.Rendering.Skia" Version="0.1.0-preview.1" />
<PackageReference Include="ArionUI.Rendering.Skia" />
paket add ArionUI.Rendering.Skia --version 0.1.0-preview.1
#r "nuget: ArionUI.Rendering.Skia, 0.1.0-preview.1"
#:package ArionUI.Rendering.Skia@0.1.0-preview.1
#addin nuget:?package=ArionUI.Rendering.Skia&version=0.1.0-preview.1&prerelease
#tool nuget:?package=ArionUI.Rendering.Skia&version=0.1.0-preview.1&prerelease
Virtualization and rendering engine for .NET data UIs
Millions of rows in freely composable views — GPU-rendered, smooth-scrolling, without creating one UI control per row. The same engine renders the same data as a table (sort / filter / editing), a card board and a tree, switchable live, with identical behaviour on WPF and Avalonia.
Early preview. The API is still moving; breaking changes are expected between preview versions.
Packages in this zone (open source, Apache-2.0)
| Package | What it carries |
|---|---|
ArionUI.Core |
The engine: virtualization, layout solving, selection, interaction, and the data sources (sorting, filtering, the typed value path) |
ArionUI.Presentation |
Templates and views — table, cards, tree — plus the composition model for cells, widgets and panes |
ArionUI.Grid |
The grid itself: presenter, input wiring, the consumer API (ArionGridApi), standard panes, accessibility |
ArionUI.Gpu |
The GPU layer: OpenGL ES 3.0 through a host-supplied loader, GL state discipline, offscreen targets with a depth buffer, shaders, streaming vertex buffers |
ArionUI.Rendering.Skia |
The Skia frame renderer, shared by all three hosts |
ArionUI.Rendering.Avalonia |
Avalonia host control (ArionGrid) |
ArionUI.Rendering.Wpf |
WPF host control (ArionGrid, D3D-backed) |
ArionUI.Rendering.WinForms |
Windows Forms host control (ArionGridControl, ANGLE-backed; brings the native ANGLE runtime as its dependency Avalonia.Angle.Windows.Natives); DataSource takes a DataTable or a BindingSource |
ArionUI.Data |
Classic .NET data binding: DataTable and DataView as live sources, Column.FromDataTable, IDataErrorInfo and INotifyDataErrorInfo as edit policy |
Grouping, pivot, charts, timeline, planning matrix, conditional formatting, layout persistence and export are separate packages and not part of this zone.
Getting started
var view = new GridView<Order>(
[
Column.Text<Order>("Customer", o => o.Customer).WithKey("customer").WithWidth(160),
TypedColumn.Number<Order>("Amount", o => o.Amount).WithWidth(90),
],
new ListItemsSource<Order>(orders),
rowHeight: 24)
.AsDataGrid();
// Avalonia or WPF — the control is the same type name on both hosts:
var grid = new ArionGrid(view);
Everything an application needs sits on one facade, grid.Api — state, selection, editing,
commands, events, panes and layout. It is the same surface on both hosts.
Language: English by default; ArionUiText.UseGermanTexts() for German (core and modules).
Avalonia on Windows: let Windows hand the picture through
For grids that update continuously, put Avalonia's low-latency swap chain first and keep its default chain behind it:
AppBuilder.Configure<App>()
.UsePlatformDetect()
.With(new Win32PlatformOptions
{
CompositionMode =
[
Win32CompositionMode.LowLatencyDxgiSwapChain,
Win32CompositionMode.WinUIComposition,
Win32CompositionMode.DirectComposition,
Win32CompositionMode.RedirectionSurface,
],
});
It needs ANGLE rendering (Avalonia's default) and a Direct3D device of feature level 11_3 or
higher; where that is missing, Avalonia takes the next mode in the list. Avalonia picks the mode
once for the whole process, so with LowLatency every window of the application loses
transparency, acrylic and mica blur. An application that needs those keeps
WinUIComposition first. Measured on a scene with a million live figures (Intel integrated
GPU): the desktop window manager's share of the GPU dropped from 16 % to 0 %, because Windows
shows the swap chain directly instead of composing the window every frame.
LowLatency windows have no redirection bitmap: PrintWindow, and UI test tools built on it,
capture them white. A copy of the screen region shows them, and so does TryWriteFramePng,
which reads the grid's own frame.
Avalonia on Windows: the render loop on the window's display
Avalonia's render loop waits for the vertical blank of the display with the highest refresh
rate, whichever window it renders. With displays of different rates - a 60 Hz display beside a
59.95 Hz one is common - a window on the other display drifts through those blanks: every
20 seconds or so its frames are presented late for a moment, and anything that moves stutters.
ArionGrid therefore paces the render loop by the blanks of the display the active window with a
grid is on, ticking on each blank: frames come evenly, about a frame later than ideal pacing
would show them - smooth rather than stuttering. Where that cannot be had, Avalonia's own timer paces
as before; so it does under native AOT, where the timer cannot be put in. To keep Avalonia's
timer, set ArionGrid.PaceRenderLoopByDisplay = false before the first grid is shown, or set the
environment variable ARION_AVALONIA_VBLANK=0.
Startup: publish with ReadyToRun
ArionUI's assemblies ship precompiled for win-x64 (ReadyToRun, the IL stays in them; other platforms compile it on first use as before). Avalonia's do not: on the first start the JIT still compiles what a window touches of them. Publishing the application with ReadyToRun precompiles those too:
<PropertyGroup>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
It takes effect when you publish for a runtime (dotnet publish -r win-x64), not on
dotnet build or dotnet run. In the showcase (framework-dependent, win-x64) the time from
process start to the first frame went from 3.2 s to 1.5 s; ArionUI's and Avalonia's assemblies
grew by about 18 MB. A composite image (PublishReadyToRunComposite) gained no more than a
few tens of milliseconds on top and needs a self-contained publish.
Startup: the shader cache
The grid's GPU cells draw with one large shader program. Under ANGLE its first compile takes
several hundred milliseconds; the cells draw on the CPU meanwhile (the same pixels), so no
frame waits for it. The linked program is then kept as the driver's binary in
%LOCALAPPDATA%\ArionUI\ShaderCache, and later starts load it in a few milliseconds. An entry
belongs to one GPU, driver and ANGLE build: after a driver update a new entry is written, an
entry the driver no longer takes is deleted and the program compiled again, and entries not
used for 30 days are removed. To keep nothing on disk, set the environment variable
ARION_SHADER_CACHE=0, or set ShaderBinaryCache.Default = null (or a cache with a folder of
your choosing) before the first grid is shown.
Live data: smoothing with LivePlayback
Live readings rarely arrive evenly: a device or a socket delivers them in packets, and a packet
is now and then a little late. Drawn as they arrive, a trace jumps by a packet at a time and
stutters at every late one. A LiveSeries keeps the readings with their times, and a
LivePlayback shows them a little behind the newest one, moving on by exactly the display time of
each frame. A row stays at one moment: the trace (Read), the value beside it (ValueOf) and
the lowest and highest over the shown window (RangeOf) are all read at the playback's position.

The cost is the delay: one packet interval plus one and a half frames, measured by the playback
itself (about 60 ms for 30 packets a second on a 60 Hz display; DelayFor tells the figure, and
ArionUiText.LiveSmoothing says it in words). Turn it off with Delay = TimeSpan.Zero where every
millisecond counts more than an even picture, such as when an operator steers by the trace in real
time: then every frame shows the newest reading, and the trace moves by whole packets.
var samples = new LiveSeries(capacity: 2048, sampleRate: 240); // the source appends, any thread
var playback = new LivePlayback(); // Delay: null = measured, Zero = off
grid.Api.Timing.Every(TimeSpan.FromMilliseconds(1), elapsed => // once per display frame
{
playback.Advance(elapsed, samples);
int n = playback.Read(samples, trace, out double shift); // the trace and how far it slid
double level = playback.ValueOf(samples); // the same moment
var (min, max) = playback.RangeOf(samples, trace.Length - 1);
});
Breaking
- The guide of a sparkline follows the pointer by default:
Column.SparklineandCell.Sparklinedefault tointerpolate: true,SparklineEl.Interpolateto true. A default parameter is compiled into the caller, so code built against an older package keeps snapping until it is recompiled; passinterpolate: falseto keep snapping on purpose. SparklineEl.Curvehas asetaccessor instead ofinit(the user switches it from the menu): recompile code that sets it.IGridViewOpshas two new members,LineCurveOfandSetLineCurve; an own implementation of the interface has to add them.ArionIcons.CheckBoxtakes five arguments: the accent colour of the box and its mark comes last ((surface, rect, state, isHot, accent)). A replacement icon adds the parameter; a caller passesPalette.Accentfor the theme's colour.- All texts are English by default — menus, dialogs, screen-reader sentences, the empty-state
title (
StandardEmptyStateTitleis "No results"), the pivot grand total ("Total") and the week caption ("CW 20"). CallArionUiText.UseGermanTexts()once at start-up (orcontext.UseGermanTexts()per grid) for the previous German texts; it switches the module catalogues (ChartTexts,PivotTexts, ...) as well. - Dates follow the culture instead of a fixed "dd.MM.yyyy":
TypedColumn.Date(formatis nowstring?) andAutoColumnOptions.DateFormatdefault to the culture's short date, the timeline and planning captions to patterns derived from it (DatePatterns). de-DE reads as before; pass a format to keep a fixed one.
License: Apache-2.0; every package carries the NOTICE file. ArionUI.Rendering.Skia embeds
JetBrains Mono (SIL OFL 1.1) and ships its licence text under THIRD-PARTY/.
Source and issues: https://github.com/ArionUI/ArionUI.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- ArionUI.Core (>= 0.1.0-preview.1)
- ArionUI.Grid (>= 0.1.0-preview.1)
- ArionUI.Presentation (>= 0.1.0-preview.1)
- HarfBuzzSharp (>= 8.3.1.5)
- SkiaSharp (>= 3.119.4)
NuGet packages (4)
Showing the top 4 NuGet packages that depend on ArionUI.Rendering.Skia:
| Package | Downloads |
|---|---|
|
ArionUI.Rendering.Wpf
WPF host control for the ArionUI data grid (ArionGrid), D3D-backed and GPU-rendered. |
|
|
ArionUI.Export
ArionUI Pro: export to CSV, XLSX and PDF. Free during the preview. |
|
|
ArionUI.Rendering.WinForms
Windows Forms host control for the ArionUI data grid (ArionGridControl), GPU-rendered on its own ANGLE window; binds DataTable, DataView and BindingSource like a DataGridView. |
|
|
ArionUI.Rendering.Avalonia
Avalonia host control for the ArionUI data grid (ArionGrid), GPU-rendered. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0-preview.1 | 79 | 10/22/2026 |
Early preview. The API is still moving; breaking changes are expected between preview versions.