Namespace: Beep.Skia.Controls — Inherits: ComboBox → MaterialControl → SkiaComponent

Overview

The ComboBox control combines an MD3-styled text field with a popup Dropdown list of selectable items, all rendered with SkiaSharp. When the user clicks the field or presses the dropdown arrow, the Dropdown overlay opens below (or above, if insufficient space) displaying the available items. The selected item is shown in the field with its text and optional icon. The dropdown closes on selection, outside click, or Escape key.

The Dropdown is an overlay component managed by OverlayManager. It renders with MD3 elevation shadow and a surface background. Items are rendered with hover and selection state layers. An animated chevron icon on the field indicates the open/closed state.

ComboBox Properties

PropertyTypeDescription
Items List<ComboBoxItem> The collection of selectable items displayed in the dropdown.
SelectedIndex int Zero-based index of the selected item. -1 when no item is selected. Setting this updates the displayed text in the field.
SelectedItem ComboBoxItem Read-only. The currently selected ComboBoxItem instance, or null.
IsOpen bool Read-only. Indicates whether the dropdown popup is currently visible.
Placeholder string Text displayed in the field when no item is selected. Rendered in OnSurfaceVariant color. Default is "Select...".
FieldStyle TextFieldStyle Enum: Filled (default) or Outlined. Controls the visual style of the combo box field.
IsEditable bool When true, the user can type in the field to filter items. The dropdown shows only items whose text contains the typed substring (case-insensitive). Default is false.
MaxDropdownHeight float Maximum height of the dropdown popup. If the total item height exceeds this, the dropdown becomes scrollable. Default is 300f.
DropdownItemHeight float Height of each item row in the dropdown. Default is 48f per MD3 list item spec.

ComboBoxItem Model

PropertyTypeDescription
Text string The display text for this item. Rendered using BodyLarge typography.
Value object Arbitrary value associated with the item. Typically a string, integer, or enum. Used for programmatic lookup when SelectedItem changes.
Icon SKPath Optional vector icon displayed before the text in the dropdown list. Not shown in the collapsed field.
IsEnabled bool When false, the item is greyed out and not selectable. Default is true.
Tooltip string Optional tooltip text shown on hover when the dropdown is open.

Code Example

Basic ComboBox

var fontCombo = new ComboBox
{
    Placeholder = "Select a font...",
    FieldStyle = TextFieldStyle.Outlined,
    X = 40,
    Y = 40,
    Width = 280,
    Height = 56,
    Items = new List<ComboBoxItem>
    {
        new() { Text = "Inter",           Value = "Inter" },
        new() { Text = "Roboto",          Value = "Roboto" },
        new() { Text = "Source Sans Pro", Value = "SourceSansPro" },
        new() { Text = "Open Sans",       Value = "OpenSans" },
        new() { Text = "Fira Code",       Value = "FiraCode" },
        new() { Text = "JetBrains Mono",  Value = "JetBrainsMono" }
    }
};

fontCombo.Initialize();

fontCombo.SelectedIndexChanged += (s, idx) =>
{
    var item = fontCombo.SelectedItem;
    Console.WriteLine($"Selected: {item.Text} ({item.Value})");
};

drawingManager.AddComponent(fontCombo);
drawingManager.RequestRedraw();

Editable ComboBox with Filtering

var countryCombo = new ComboBox
{
    Placeholder = "Search countries...",
    IsEditable = true,
    FieldStyle = TextFieldStyle.Filled,
    X = 40,
    Y = 120,
    Width = 300,
    Height = 56,
    Items = new List<ComboBoxItem>
    {
        new() { Text = "Argentina",    Value = "AR" },
        new() { Text = "Australia",    Value = "AU" },
        new() { Text = "Brazil",       Value = "BR" },
        new() { Text = "Canada",       Value = "CA" },
        new() { Text = "France",       Value = "FR" },
        new() { Text = "Germany",      Value = "DE" },
        new() { Text = "India",        Value = "IN" },
        new() { Text = "Japan",        Value = "JP" },
        new() { Text = "Mexico",       Value = "MX" },
        new() { Text = "Netherlands",  Value = "NL" },
        new() { Text = "Spain",        Value = "ES" },
        new() { Text = "United Kingdom", Value = "UK" },
        new() { Text = "United States",  Value = "US" }
    }
};

countryCombo.Initialize();
drawingManager.AddComponent(countryCombo);

Programmatic Selection

themeCombo.SelectedIndex = 1;

var targetItem = themeCombo.Items
    .FirstOrDefault(i => i.Value?.ToString() == "Dark");
if (targetItem != null)
    themeCombo.SelectedIndex = themeCombo.Items.IndexOf(targetItem);

themeCombo.OpenDropdown();
themeCombo.CloseDropdown();

ComboBox with Icons

var sizeIcon = SKPath.ParseSvgPathData(
    "M3 3h18v2H3V3zm0 4h14v2H3V7zm0 4h18v2H3v-2zm0 4h12v2H3v-2z");

var sizeCombo = new ComboBox
{
    Placeholder = "Text Size",
    X = 40, Y = 200,
    Width = 200, Height = 56,
    Items = new List<ComboBoxItem>
    {
        new() { Text = "Small",  Value = 12f, Icon = sizeIcon },
        new() { Text = "Medium", Value = 16f, Icon = sizeIcon },
        new() { Text = "Large",  Value = 20f, Icon = sizeIcon },
        new() { Text = "Extra Large", Value = 24f, Icon = sizeIcon }
    }
};

sizeCombo.Initialize();
sizeCombo.SelectedIndex = 1;
drawingManager.AddComponent(sizeCombo);

Note

The Dropdown overlay is positioned relative to the ComboBox's location on the canvas. It does not account for window bounds automatically — use DropDirection.Auto and ensure the ComboBox is placed with enough vertical space. For window-edge detection, listen to OverlayManager.BoundsChanged.