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.
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.
// 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.
// 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" }
});
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.
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 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.).
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.
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.
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);
}
}