This document captures design and implementation notes for Select<T> (a compact dropdown).
For end-user usage and examples, see Select / Dropdown.
Popup for dismissal behaviors (outside click, Esc, Tab, etc.)SelectionList<T> / other list controls)ListBox<T>)src/XenoAtom.Terminal.UI/Controls/Select.cssrc/XenoAtom.Terminal.UI/Styling/SelectStyle.cssrc/XenoAtom.Terminal.UI.Tests/SelectTests.cssamples/ControlsDemo/Demos/SelectDemo.csSelect<T> : ContentVisualItems : BindableList<T>
SelectedIndex : int (bindable)
[0 .. Items.Count - 1] when Items.Count > 0.Items.Count == 0, the internal selected content is cleared and the effective selected index is -1.ItemTemplate : DataTemplate<T> (bindable)
DataTemplates (role: Display).value.ToString() in a TextBlock.SelectionChanged routed event (bubble).
Select<T> uses the ContentVisual.Content slot to render the selected value.
The selected content is updated on:
SelectedIndex changesItemTemplate changes (forced rebuild)Template resolution for the selected content is:
ItemTemplate if non-emptyDataTemplates.TryResolve(DataTemplateRole.Display, out template) from the environmentWhen the selected value is not a Visual, the control creates the visual via DataTemplate<T>.Display(...).
To avoid rebuilding visuals on every selection update, it uses DataTemplate<T>.TryUpdate when all of the following
conditions are true:
Content visualTryUpdate returns trueWhen the selected value is already a Visual, the control uses it directly as Content (no template is applied).
Select<T> measures as a single-line control with a content area and a trailing arrow indicator.
Key details:
SelectStyle.ArrowGlyph using TerminalTextUtility.GetWidth(...).constraints.MaxWidth - style.Padding.Horizontal - arrowWidth (when finite)style.Padding.Horizontal + arrowWidth to widthstyle.Padding.Vertical to height3 cells.1 cell.Arrange places the selected Content inside an inner rectangle:
inner = finalRect minus SelectStyle.PaddingarrowWidthRender performs two operations:
Bounds rectangle with spaces using the resolved style (a stable background baseline)TextStyle.DimImplementation note: the arrow is currently written on the first row (y = Bounds.Y), even if the control is taller
than 1 cell.
Enter / Space: open the popup.Up / Down (when the popup is closed): quick selection changes by +/- 1 within [0 .. Items.Count - 1].Select<T> currently implements these behaviors directly in OnKeyDown / OnPointerPressed (it does not register
commands for them yet).
When opened, Select<T> creates a Popup with:
Anchor = thisPlacement = BelowMatchAnchorWidth = true (dropdown matches the collapsed control width)AdditionalWidth = 2 (extra space for borders/padding in the popup template)The popup content is a ListBox<T> configured with:
.Items(Items) (same list instance as the owner).ItemTemplate(resolvedTemplate)SelectedIndex initialized to the clamped owner selectionThe list is optionally wrapped via SelectStyle.PopupTemplateFactory (default: wraps with a Border that stretches).
owner.SelectedIndex = list.SelectedIndex and closes the popup.Enter / Space in the list selects and closes the popup.Select<T>.Dismissal mechanisms like "click outside" / Esc / Tab are handled by the Popup control.
SelectStyle controls:
PaddingArrowGlyphNormalStyle, HoverStyle, FocusedStyle, DisabledStylePopupTemplateFactory for wrapping the dropdown list surfaceDefault behavior:
Theme.Foreground and applies TextStyle.Bold on focus
and TextStyle.Dim when disabled.Open, SelectNext, SelectPrevious) to improve CommandBar discoverability.ListBox<T> does not provide the desired experience for dropdown use cases).