The grid API
Everything an application does with a grid goes through one object, grid.Api. It is the same object on Avalonia, WPF and WinForms, so code written against it does not change with the host.
The facade is grouped, because a flat surface of this size stops being findable. The host controls add bindable properties on top of it for MVVM (see MVVM and binding); underneath, those properties write into the same objects. For every member and signature, see the API reference.
What is on it
| Member | What it holds |
|---|---|
State | Theme, context, scroll position and extent, loading and empty state, read-only, behaviour switches (CanUserSortColumns and its siblings, smooth scrolling, tooltips, the selection footer). |
Layout | Frozen rows and columns (left and right), the filter row, zoom, column count, cell bounds, refresh. |
Selection | What is selected and the current cell; set it by position or by item. See Selection and clipboard. |
Editing | Open, type, commit, cancel, or set a value in one call. See Editing and validation. |
Commands | ICommands for a toolbar (undo, redo, copy, paste, select all, search, clear filters …) and the methods behind them. |
Events | Selection, edits, row activation, button clicks, context menus, column moves, view changes. |
Filters | The complete filter state as a serializable object: capture, apply, clear, changed. |
Actions | The item-addressed operations a view model needs: scroll to, select, begin edit, set value. |
Rows | Open and close groups, tree nodes and detail bands by item. |
Presentation | Providers for tooltips, column headers, the empty state and the loading text; a rounded frame; the day the date picker treats as today. |
Panes | The stack of drawn panes — filter lists, menus, pickers — including panes of your own. |
CommandInputs | The ICommands and the edit policy a view model hands into the grid. |
Timing | A tick in step with the frames, for data pushed on a clock. |
Accessibility | What the screen-reader layer sees; Announce for messages of your own. |
Testing | A driver for UI tests: clicks, keys, typing and a state line, without a real mouse. |
Engine | The engine underneath: GetItem(index) for the item at a view row. |
State and appearance
var api = grid.Api;
api.State.VisualTheme = ArionTheme.Dark();
api.Layout.FrozenColumns = 1; // keep the first column in place
api.State.IsLoading = true; // the drawn loading state ...
api.State.LoadingText = "Loading orders";
api.State.EmptyStateTitle = "No orders"; // ... and the drawn empty state
api.State.EmptyStateMessage = "Orders you create appear here.";
api.State.ScrollChanged += pos => Log($"{pos.FirstVisibleItem} of {pos.VisibleRowCount}");State.Changed reports every property change as a GridStateChange(PropertyName, OldValue, NewValue). The empty state draws in the grid itself; besides title and message it can carry an action button (EmptyStateActionLabel with EmptyStateAction or EmptyStateCommand).
Events
api.Events.RowActivated += item => Open((Order)item); // double-click on a row
api.Events.SelectionChanged += e => Log($"{e.SelectedItems.Count} selected");
api.Events.CellEditCommitted += e => Save(e.Item, e.ElementId, e.NewValue);
api.Events.ViewChanged += e => Log($"view changed: {e.Changes}"); // sort, filter, group ...RowActivated passes the row's data item, not its index, because an index shifts with every sort and filter; it is raised by a double-click on a row. ButtonClicked reports the item index and the element id of a Column.Button or a Cell.Button. A few events let the application take over a gesture: if something handles SearchRequested, Ctrl+F opens your search instead of the grid's, and the same holds for QuickSearchRequested and ClearFiltersRequested.
Element ids and column positions
Columns are addressed two ways, and mixing them up only shows once a user has moved a column. An element id is the column's identity: it is assigned when the view is built and does not change when columns are reordered or hidden. A column index is the visible position.
int amountId = view.ColumnIdOfKey("amount"); // stable: the column's identity
int firstVisibleId = view.ElementIdAt(0); // what sits at visible position 0 nowEvents, filters, sorting and the Pro modules speak element ids. Selection.Set, Selection.SetRange and Editing.SetValue take a visible column index, like the keyboard does; GridCellRef carries both. The item-addressed calls on Actions take the column key, which is the safest of the three.
Acting on items
api.Actions.ScrollTo(order); // false if filtered away
api.Actions.SelectItems(new[] { order });
api.Actions.SetValue(order, "amount", "120"); // through the normal edit path
api.Commands.Copy(withHeaders: true);
api.Commands.AutoSizeAllColumns();Actions.SetValue goes through the same path as typing — validation, the edit policy, the edit events and undo all apply — and returns a GridEditOutcome. Items are found by reference first and by Equals only as a fallback, with a scan of the current view.
Presentation hooks
api.Presentation.CellTooltipProvider = c => c.IsTextTruncated ? c.DisplayText : null;
api.Presentation.EmptyStateProvider = c => c.HasActiveFilters
? new GridEmptyStateContent("No matches", "Clear the filters to see all orders.")
: null; // null: the standard empty state
api.Presentation.ColumnHeaderProvider = h => h.HasActiveFilter
? new GridColumnHeaderContent(Foreground: Palette.Accent)
: null;A provider returning null keeps the standard behaviour, and members left null in its result fall back to the defaults. The default tooltip shows the full text of a truncated cell.
Context menus
The grid builds its own cell and header menus. The events hand you the entry list before it opens, so you extend the menu rather than replace it:
api.Events.CellContextMenuRequested += e =>
{
if (api.Engine.GetItem(e.ItemIndex) is not Order clicked)
{
return;
}
e.Entries.Add(MenuItem.Separator());
e.Entries.Add(new MenuItem("Open order", () => Open(clicked)));
};HeaderContextMenuRequested works the same way for the column header. Panes of your own — anything derived from ControlPaneContent — open with Api.Panes.Show and close with Api.Panes.CloseAll.
When your code throws
Column getters, tooltips and chart series are your code, called by the grid. When one of them throws outside the drawing of a frame, the grid reports it instead of crashing:
api.DataReadFailed += failure => Log($"{failure.Source}: {failure.Exception.Message}");
GridDiagnostics.Reported += d => Log($"{d.Kind} {d.Source}: {d.Message}");DataReadFailed names the reader — "tooltip", "accessibility", "hit-test", "autosize" — and repeated failures from the same reader are damped. GridDiagnostics.Reported is process-wide and carries subscriber failures, unavailable platform features and state that could not be applied.
