ColumnDefinition<T> class Core
Typed, declarative description of ONE grid column — the consumer-facing API.
A GridView turns a list of these into its internal drawing model and erases Func<T,…> to Func<object,…> ONCE at build time; concrete return types mean no per-frame boxing.
Built via the fluent Column factory. Sort, filter and grouping all key off the element id the view assigns, so reordering columns never breaks them.
public sealed class ColumnDefinition<T> : IColumnDefinition, IColumnCell
- Namespace
- ArionUI.Presentation
- Package
- ArionUI.Presentation ·
dotnet add package ArionUI.Presentation --prerelease - Implements
- IColumnDefinition, IColumnCell
Constructors
ColumnDefinition
public ColumnDefinition();
Properties
AccessibleText
public Func<T, string>? AccessibleText { get; set; }What a screen reader SPEAKS for this cell (null = the display text). See ColumnDefinition.SpeakAs.
Align
public TextAlign Align { get; set; }
BadgeColor
public Func<T, Rgba>? BadgeColor { get; set; }
BadgeLabel
public Func<T, string>? BadgeLabel { get; set; }
BandPath
public IReadOnlyList<string>? BandPath { get; set; }Banded-header grouping path (outermost first) — see ColumnDefinition.Band.
ButtonLabel
public Func<T, string>? ButtonLabel { get; set; }
CheckboxGet
public Func<T, bool>? CheckboxGet { get; set; }
CheckboxSet
public Action<T, bool>? CheckboxSet { get; set; }
CheckboxState
public Func<T, bool?>? CheckboxState { get; set; }Optional tri-state getter for the drawn checkbox: null result = indeterminate (dash). Wins over ColumnDefinition.CheckboxGet for DRAWING; a "(select all)" row uses it. Toggle still goes through the click handler.
Composition
public SlotEl? Composition { get; set; }Composed cell: a SlotEl tree drawn as the whole cell content — wins over the simple kinds above. Built via the typed Cell factory (Row/Stack/Text/Badge/Tag/Button/ Progress/Spacer).
CompositionInset
public double? CompositionInset { get; set; }Horizontal inset of a COMPOSED cell's content box; null = the theme's cell padding. Chip/icon-button columns set 0: their composition IS a boxed control that budgets its own margins, and the default padding would push its overflow under the neighbour cell's background.
CustomSummaries
public List<string> CustomSummaries { get; }Labels of the custom aggregates currently shown (footer and groups).
CustomSummaryOptions
public List<AggregateSpec> CustomSummaryOptions { get; }Custom aggregates this column offers (median, distinct count, a weighted mean): each an AggregateSpec with a Custom delegate, keyed by its label. They run in the footer and per group over the same path as the built-in ones and appear in the Σ menu under their label.
DataType
public ColumnDataType? DataType { get; set; }Value kind of the column — drives the filter-operator set (text matching vs. numeric/date comparison). Null = infer: Number when a numeric projection (ColumnDefinition.SummaryValue) exists, else Text.
DateCommitFormat
public string? DateCommitFormat { get; set; }.NET date format the calendar COMMITS the picked day with (the column's setter must parse it). Null = the culture short-date ("d").
DateEditor
public bool DateEditor { get; set; }Edit this column via a CALENDAR picker (see ColumnDefinition.WithDateEditor).
DateValue
public Func<T, DateTime?>? DateValue { get; set; }Current date value for the calendar's initial selection (else the display text is parsed). Only used when ColumnDefinition.DateEditor is set.
DropDownButton
public DropDownButtonMode DropDownButton { get; set; }When the ▾ dropdown button shows in a combo/date cell (hover by default). A single click on the button opens the picker.
DropDownStyle
public DropDownStyle DropDownStyle { get; set; }Look of the combo picker for this column (menu vs. classic).
EditOptions
public Func<T, IReadOnlyList<string>>? EditOptions { get; set; }Fixed choices for the editor (combo picker). Null = free text.
EditText
public Func<T, string>? EditText { get; set; }Raw text the EDITOR opens with (e.g. "1234.5" behind a display text of "1.234,50 €"). Null = the display text — fine for plain columns, wrong for formatted ones (the user would edit the formatting).
FillWeight
public double FillWeight { get; set; }Star-sizing weight (0 = fixed). See ColumnDefinition.Fill.
Filterable
public bool Filterable { get; set; }Every column with display text is filterable (filter cell, value list); ColumnDefinition.NotFilterable opts one out.
Groupable
public bool Groupable { get; set; }
GroupKey
public Func<T, object?>? GroupKey { get; set; }Group bucket key (defaults to ColumnDefinition.SortKey).
GroupLabel
public Func<object?, string>? GroupLabel { get; set; }Friendly label for a group's key value (defaults to ToString()).
Header
public required string Header { get; init; }Caption — the one thing every consumer of a column list needs without knowing the row type.
InputMask
public string? InputMask { get; set; }Optional input mask for the editor (e.g. "00.00.0000"), or null for free text. See InputMask for the syntax.
IsExpander
public bool IsExpander { get; set; }Master-detail expander column (chevron cell) — see Column.Expander.
IsNullable
public bool IsNullable { get; set; }Allow the cell to be cleared to an empty value: an empty edit passes type validation (Number/Date) instead of being rejected, so the setter can store null. See ColumnDefinition.Nullable.
Key
public string? Key { get; }Application-stable identity used by persisted layouts.
MaskPromptChar
public char MaskPromptChar { get; set; }Prompt char shown at unfilled mask slots (default '_'). Set to ' ' (space) to hide the prompt — see ColumnDefinition.WithInputMask.
MaxTextLines
public int MaxTextLines { get; set; }How many lines this column's text may wrap onto. 1 (the default) keeps the single-line behaviour. Above 1 the cell wraps and the last visible line is ellipsized — set a row height that fits, since the row does NOT grow to the content (a height that follows today's longest value moves the whole layout the moment the data changes).
PlainText
public Func<T, string>? PlainText { get; set; }Plain-text projection of the cell for a column that draws no single label of its own (a composition, or a button-only cell). Supplies the text that filter-row "contains" matching and TSV copy need — the visual kinds (Text/Badge/Tag) already carry their own label.
RowType
public Type RowType { get; }The row type this column was built for. A view checks it before accepting the column: a definition for the wrong type would draw and then fail on the first sort, which is a far worse failure than being rejected here.
Rules
public List<StyleRule> Rules { get; }
SelectAllOnEdit
public bool? SelectAllOnEdit { get; set; }Per-column override of "select the whole content when the cell enters edit mode" (null = inherit the grid default). See ColumnDefinition.WithSelectAllOnEdit.
SetText
public Action<T, string>? SetText { get; set; }Set ⇒ the column is editable; commit writes back through this.
SortComparer
public IComparer<object?>? SortComparer { get; set; }Custom ordering of the sort keys — see ColumnDefinition.SortWith.
SortKey
public Func<T, object?>? SortKey { get; set; }Set ⇒ sortable; also the default group key.
SummaryFns
public List<AggregateFn> SummaryFns { get; }Aggregates shown for this column in the grand-total footer AND per group (Sum/Count/Avg/Min/Max — several at once, stacked). Empty ⇒ none. Mutable at runtime via the header Σ menu (GridView.ToggleSummary).
SummaryFormat
public Func<decimal, string>? SummaryFormat { get; set; }Per-column text override (else the central ArionFormats.Summary default is used) — the per-column localization/formatting hook.
SummaryOptions
public List<AggregateFn>? SummaryOptions { get; set; }Which aggregates the Σ menu OFFERS for this column (dev override). Null = the default: all five when ColumnDefinition.SummaryValue is set, otherwise none. Set e.g. to [Count] to offer Count on a text column, or to [Sum] to restrict a numeric column.
SummaryValue
public Func<T, decimal>? SummaryValue { get; set; }Numeric value the value-aggregates (Sum/Avg/Min/Max) read. Not needed for Count. A column with this set is "summable" — the Σ menu offers all five; without it only Count is offered.
Tag
public object? Tag { get; set; }Application data attached to the column — what a generated column MEANS. Never read by the grid; reachable via GridView.DefinitionByElementId.
TagColor
public Func<T, Rgba>? TagColor { get; set; }
TagLabel
public Func<T, string>? TagLabel { get; set; }
Text
public Func<T, string>? Text { get; set; }Display text (text columns). Badge/tag/button columns use their own label instead.
TextOverflow
public TextOverflow? TextOverflow { get; set; }Per-column overflow override; null = inherit the theme default (ArionTheme.CellTextOverflow). Set via ColumnDefinition.Ellipsis / ColumnDefinition.Clip.
Tooltip
public Func<T, double, string>? Tooltip { get; set; }Per-column hover tooltip (null/empty = none). Without one, the grid still shows a truncated cell's full text; an app-level Presentation.CellTooltipProvider overrides both. What a CHART cell needs: its pixels truncate never, its DESCRIPTION belongs on hover.
Remarks
The second argument is the DATA POINT under the pointer (-1 = none) — which value of a sparkline, which segment of a stack. It comes from the same resolve that draws the point cursor, so the tooltip names exactly the value the line marks.
TreeLabel
public Func<T, string>? TreeLabel { get; set; }TreeGrid hierarchy-column label projection — see Column.Tree.
ValidationMessage
public Func<string, string?>? ValidationMessage { get; set; }Per-column edit validation: input text → error message (null = valid). Runs ON TOP of the data-type parse check; the editor shows the message and refuses to commit while one is returned.
Width
public double Width { get; set; }
Methods
Band
public ColumnDefinition<T> Band(params string[] path);Group this column under a banded header (outermost segment first, e.g. .Band("KW 20", "Mo 11.05")). Adjacent columns sharing a path prefix render as one spanning band cell above the caption.
Center
public ColumnDefinition<T> Center();
ClassicDropDown
public ColumnDefinition<T> ClassicDropDown();Render this column's combo picker in the classic framed look.
Clip
public ColumnDefinition<T> Clip();Hard-clip over-wide text in this column at the cell edge.
Editable
public ColumnDefinition<T> Editable();Mark the column editable WITHOUT a per-item setter — the commit is handled centrally (a TreeView cell-editor / spread callback). The editor opens; the value write goes through the interceptor.
Editable
public ColumnDefinition<T> Editable(Action<T, string> setter);
Ellipsis
public ColumnDefinition<T> Ellipsis();Truncate over-wide text in this column with "…".
Fill
public ColumnDefinition<T> Fill(double weight = 1);Star-sizing: this column takes the viewport width left over after the fixed columns (several fill columns share it by weight). ColumnDefinition.Width becomes the column's MINIMUM; a manual resize converts it back to fixed.
NotFilterable
public ColumnDefinition<T> NotFilterable();Take the filter away from this column: no filter cell, no funnel, skipped by the filter-row keyboard walk.
Nullable
public ColumnDefinition<T> Nullable(bool value = true);Mark the column nullable — an empty edit is valid (the setter receives "" and can store null). Without this a Number/Date column rejects empty input and reverts to the old value.
Right
public ColumnDefinition<T> Right();
Searchable
public ColumnDefinition<T> Searchable(Func<T, string> text);Give a composed/button column a plain-text projection so it can be filtered and copied (it draws no single label the grid could reuse).
Sortable
public ColumnDefinition<T> Sortable(Func<T, object?> key);Sortable by an explicit key (e.g. the raw number behind a formatted amount). Also becomes the default group key.
SortWith
public ColumnDefinition<T> SortWith<TKey>(Comparison<TKey> comparison);Convenience over the column's KEY TYPE: casts to TKey and delegates — the key comes from ColumnDefinition.Sortable, so the caller knows its type.
SortWith
public ColumnDefinition<T> SortWith(IComparer<object?> comparison);Custom ordering for this column: the comparer orders the SORT KEYS (ColumnDefinition.Sortable values), not the items, and applies to sorting, grouping and the filter pane alike.
Nulls-first stays with the engine — the comparer only sees non-null pairs. If it throws, it is disabled and reported once; the column then orders by the built-in value order.
For TEXT order instead of value order no comparer is needed: Sortable(z => displayText(z)) says exactly that.
SpeakAs
public ColumnDefinition<T> SpeakAs(Func<T, string> speak);What a screen reader SPEAKS for this cell, when the visual text is not speakable — a checkmark glyph ("✓") should say "aktiv", a color-only tag its meaning.
This is the developer's half of the narration contract: the GRID owns the scaffolding (position, selection, timing), the APPLICATION owns the content — and by default that content is simply the column's display text, so nothing needs to be done twice. This override exists for the cells where eye and ear diverge.
Style
public ColumnDefinition<T> Style(Func<T, bool> when, Rgba? foreground = default, bool bold = false, Rgba? background = default);Conditional formatting: when when matches the row, apply the given foreground/weight/background to this cell.
Summable
public ColumnDefinition<T> Summable(Func<T, decimal> value);Declare the column summable (Σ menu offers all five aggregates) without activating any summary yet.
SummableWith
public ColumnDefinition<T> SummableWith(string label, Func<IReadOnlyList<int>, IItemsSource, decimal> compute, Func<decimal, string>? format = null);Offer a custom aggregate in the Σ menu without showing it yet.
Summary
public ColumnDefinition<T> Summary(AggregateFn fn, Func<T, decimal>? value = null, Func<decimal, string>? format = null);Add an aggregate to this column's summaries (Sum/Avg/Min/Max need value; Count does not). Call more than once to stack several. format overrides the displayed text for this column (else the central ArionFormats.Summary default applies).
Summary
public ColumnDefinition<T> Summary(string label, Func<IReadOnlyList<int>, IItemsSource, decimal> compute, Func<decimal, string>? format = null);Show a CUSTOM aggregate for this column: compute gets the item indexes and the source of the set it summarises (the filtered view for the footer, the group's leaves per group). format defaults to the plain number.
SummaryChoices
public ColumnDefinition<T> SummaryChoices(params AggregateFn[] fns);Dev override of WHICH aggregates the Σ menu offers for this column (else the default: all five when summable, otherwise none). Use e.g. SummaryChoices(AggregateFn.Count) to offer Count on a text column, or a subset to restrict a numeric one. Value aggregates still need a numeric projection via ColumnDefinition.Summable or ColumnDefinition.Summary.
Validate
public ColumnDefinition<T> Validate(Func<string, string?> validator);Custom edit validation: input → error text (null = valid).
WithCompositionInset
public ColumnDefinition<T> WithCompositionInset(double inset);
WithDataType
public ColumnDefinition<T> WithDataType(ColumnDataType type);Declare the column's value kind explicitly (e.g. Date).
WithDateEditor
public ColumnDefinition<T> WithDateEditor(Func<T, DateTime?>? value = null, string? commitFormat = null);Edit this column with a CALENDAR picker (double-click / F2 opens it; the pick commits through the normal edit path — the column's setter parses the date string). value gives the calendar its initial selection; omit it to parse the display text. Marks the column ColumnDataType.Date unless a type was set explicitly.
WithDateFormat
public ColumnDefinition<T> WithDateFormat(string format);The exact format the column's text is written and read in, without a calendar: validation, the filter row and date grouping parse it format-first, so a dd.MM.yyyy column stays readable under any UI culture.
WithDropDownButton
public ColumnDefinition<T> WithDropDownButton(DropDownButtonMode mode);Control when the ▾ dropdown button shows (hover / always / never).
WithEditOptions
public ColumnDefinition<T> WithEditOptions(Func<T, IReadOnlyList<string>> options, DropDownStyle style = default);Give the editor a fixed choice list (combo picker) instead of free text. Requires an editable setter so the pick can be committed. style picks the look (menu / classic).
WithEditText
public ColumnDefinition<T> WithEditText(Func<T, string> raw);Give the editor a RAW text projection (see ColumnDefinition.EditText).
WithGrouping
public ColumnDefinition<T> WithGrouping(Func<T, object?>? key = null, Func<object?, string>? label = null);
WithInputMask
public ColumnDefinition<T> WithInputMask(string mask, char promptChar = '_');Constrain the editor to an input mask (e.g. "00.00.0000" for a date, "(000) 000-0000" for a phone). promptChar is the placeholder shown at unfilled slots — pass ' ' (space) to hide the prompt. See InputMask.
WithKey
public ColumnDefinition<T> WithKey(string key);
WithSelectAllOnEdit
public ColumnDefinition<T> WithSelectAllOnEdit(bool selectAll = true);Override whether entering edit mode selects this column's whole content (else places the caret) — overrides the grid default.
WithValue
public ColumnDefinition<T> WithValue<TValue>(Func<T, TValue?> get, Func<string, TValue?>? read = null, Func<TValue, decimal>? asNumber = null) where TValue : struct;Declares which typed VALUE the column carries. The display text stays what the user sees; counting and ordering use this value (otherwise a number column orders lexicographically: "1, 10, 11, 2, ...").
Parameters
readParses a search text into this value space — the column knows its culture and format, the filter does not. Without a reader the filter falls back to text comparison.
asNumberNumeric view of the value — number columns only; the export writes a real numeric cell with it instead of a string.
WithWidth
public ColumnDefinition<T> WithWidth(double width);
WithWrap
public ColumnDefinition<T> WithWrap(int lines = 2);Let this column's text wrap onto up to lines lines. Pair it with a taller row height — the row does not grow by itself.
