Siticone Logo
Siticone UI
DOCS
v2025.12.15
Docs Command Palette

Siticone Command Palette

The SiticoneCommandPalette provides a modern in-app command launcher (Ctrl+K style) for WinForms. It enables users to quickly search and execute actions you register, similar to command palettes found in IDEs and developer tools. It is designed for professional desktop applications: fast, keyboard-centric, and themable.

Important: This palette searches your application’s commands (what you register), not the operating system. If you want OS-like results, you can add them via custom providers.

Key Features

Fuzzy search across commands, descriptions, groups, and keywords.
UI-safe execution (commands run on the UI thread to avoid WinForms cross-thread freezes).
Async execution overlay for long-running operations (optional).
Provider model for dynamic commands (context-aware, per-form, per-selection, etc.).
Maximize/resize safe overlay that tracks the host form’s client bounds.
Owner-draw variable height list items so text doesn’t clip with custom fonts.

Quick Start

Drop a SiticoneCommandPalette component onto your form (or instantiate it), register commands, and attach a hotkey.

Attach Ctrl+K and register commands
// Register commands (sync UI-safe actions)
siticoneCommandPalette1.RegisterCommand(
                new SiticoneCommand("Click expressive button", () =>
    {
        siticoneExpressiveButton1.PerformClickEx();
    })
    {
        ShortcutText = "Ctrl+,",
        Description  = "Triggers the expressive button action",
        Group        = "UI"
    });

siticoneCommandPalette1.RegisterCommand(
                new SiticoneCommand("Toggle expressive switch", () =>
    {
        siticoneExpressiveToggleSwitch1.Toggle();
    })
    {
        ShortcutText = "Ctrl+T",
        Description  = "Toggles the expressive switch",
        Group        = "UI"
    });

siticoneCommandPalette1.RegisterCommand(
                new SiticoneCommand("Close the app", () => Close())
    {
        ShortcutText = "Ctrl+W",
        Group        = "Application"
    });

// Attach hotkey (Ctrl+K opens the palette)
siticoneCommandPalette1.AttachTo(this, Keys.Control | Keys.K);

Defining Commands

Commands are represented by SiticoneCommand. Each command can be synchronous (Action) or asynchronous (Func<Task>). Use Description, Group and Keywords to improve discoverability.

Member Type Description
Text string Main display text shown in the palette list.
Description string Secondary line for guidance (shown under the title).
Group string Optional group label (also helps search relevance).
ShortcutText string Right-side hint (e.g., Ctrl+S).
Keywords string[] Extra terms (aliases, synonyms) to improve fuzzy search.
Execute Action Synchronous execution delegate (UI thread).
ExecuteAsync Func<Task> Async execution delegate (awaited with overlay support).

Async Commands + Running Overlay

For long-running operations (network, database, IO), register an async command. When configured, the palette shows a “Running…” overlay and a marquee progress bar while the command executes.

Async command example (with overlay)
// Configure async overlay behavior
siticoneCommandPalette1.ShowExecutionOverlayForAsync = true;
siticoneCommandPalette1.ExecutionOverlayTextFormat   = "Running: {0}";
siticoneCommandPalette1.ExecutionOverlayMinVisibleMs = 250;

// Register an async command
siticoneCommandPalette1.RegisterCommand(
                new SiticoneCommand("Refresh customer list", async () =>
    {
                // Your async IO here (keep it truly async)
                await customerService.ReloadAsync();
                await gridBinder.RefreshAsync();
    })
    {
        ShortcutText = "Ctrl+R",
        Description  = "Reload customers from the server",
        Group        = "Data",
        Keywords     = new[] { "reload", "sync", "customers" }
    });
Best practice: Keep async commands non-blocking. If you do heavy CPU work, offload it inside your command using await Task.Run(...) (but keep UI updates on the UI thread).

Dynamic Commands via Providers

Providers allow you to generate commands dynamically at runtime. This is ideal for context-aware actions: active document operations, selected item actions, per-user commands, or feature-gated commands.

Custom command provider example
public sealed class TabsCommandProvider : ISiticoneCommandProvider
{
                private readonly TabControl _tabs;

                public TabsCommandProvider(TabControl tabs)
    {
        _tabs = tabs;
    }

                public IEnumerable<SiticoneCommand> GetCommands(SiticoneCommandContext context)
    {
                if (_tabs == null || _tabs.TabPages.Count == 0)
                yield break;

                yield return new SiticoneCommand("Close active tab", () =>
        {
                var i = _tabs.SelectedIndex;
                if (i >= 0) _tabs.TabPages.RemoveAt(i);
        })
        {
            Group       = "Tabs",
            ShortcutText = "Ctrl+W",
            Keywords    = new[] { "remove", "tab", "close" }
        };

                yield return new SiticoneCommand("Next tab", () =>
        {
                if (_tabs.TabPages.Count <= 1) return;
            _tabs.SelectedIndex = (_tabs.SelectedIndex + 1) % _tabs.TabPages.Count;
        })
        {
            Group = "Tabs"
        };
    }
}

// Register provider
siticoneCommandPalette1.AddProvider(new TabsCommandProvider(tabControl1));

Manual Show/Hide

Besides hotkeys, you can show or hide the palette programmatically. This is useful for toolbar buttons, menu items, or onboarding prompts.

Show/Hide programmatically
// Show on-demand
siticoneCommandPalette1.Show(this);

// Hide
siticoneCommandPalette1.Hide();

Events

Use the Invoked event to react when a command is executed (telemetry, logging, status updates, etc.).

Handle Invoked event
siticoneCommandPalette1.Invoked += (s, cmd) =>
{
                // Example: log the executed command
    auditLogger.Log("CommandInvoked", cmd.Text);

                // Example: update a status bar
    statusLabel.Text = "Executed: " + cmd.Text;
};

Theming & Behavior Properties

The palette exposes a professional set of public properties for layout, fonts, colors, and behavior. These make it straightforward to integrate with your Siticone theming/tokens.

Property Type Purpose
PanelWidth, PanelTop, CornerRadius int Controls the palette panel size and placement.
OverlayOpacity, OverlayPadding double, int Overlay density and spacing.
MaxResults int Limits results displayed for fast navigation.
ClosePaletteOnInvoke bool Closes palette after a command runs (common UX).
ReopenPaletteAfterInvoke, ReopenDelayMs bool, int Re-opens palette after execution (power workflows).
ShowExecutionOverlayForAsync bool Displays a running overlay for async commands.
ExecutionOverlayTextFormat string Overlay label format (e.g., "Running: {0}").
ExecutionOverlayMinVisibleMs int Prevents overlay flicker on fast async operations.
TitleFont, SearchFont, ItemTitleFont, ItemDescriptionFont Font Typography customization (variable-height items adapt automatically).
OverlayBackColor, PanelColor, ForeColor, MutedTextColor Color Theme colors for overlay and palette surface.
AccentColor, ItemSelectedColor, ItemHoverColor Color Brand accent and selection states.

Power Workflow: Re-open After Invoke

If you want a “command chain” workflow (execute multiple commands quickly), you can automatically re-open the palette after each invocation.

Reopen palette after a command runs
siticoneCommandPalette1.ClosePaletteOnInvoke      = true;
siticoneCommandPalette1.ReopenPaletteAfterInvoke  = true;
siticoneCommandPalette1.ReopenDelayMs             = 120;

Full Sample

A compact, production-ready pattern: register commands, attach a hotkey, add a provider, and log invocations.

Complete setup pattern
public partial class MainForm : Form
{
                private readonly SiticoneCommandPalette _palette = new SiticoneCommandPalette();

                public MainForm()
    {
                InitializeComponent();

        _palette.Title = "Command Palette";
        _palette.MaxResults = 10;

        _palette.RegisterCommand(
                new SiticoneCommand("Open Settings", () => OpenSettings())
            {
                ShortcutText = "Ctrl+,",
                Group = "Application",
                Keywords = new[] { "preferences", "options" }
            });

        _palette.RegisterCommand(
                new SiticoneCommand("Refresh Data", async () =>
            {
                await dataService.ReloadAsync();
            })
            {
                ShortcutText = "Ctrl+R",
                Group = "Data"
            });

        _palette.AddProvider(new TabsCommandProvider(tabControl1));

        _palette.Invoked += (s, cmd) => auditLogger.Log("Invoked", cmd.Text);

        _palette.AttachTo(this, Keys.Control | Keys.K);
    }

                private void OpenSettings()
    {
                using (var dlg = new SettingsDialog())
            dlg.ShowDialog(this);
    }
}