Loading...
Loading...
Use when designing, reviewing, or fixing WinUI 3: layout planning, control choice, Fluent Design alignment, Light/Dark/High Contrast theming, typography, spacing, brushes, accessibility, and XAML data-binding design. Load before authoring new XAML, reviewing UI PRs, migrating desktop UI to WinUI, or choosing between WinUI controls/patterns.
npx skill4agent add microsoft/win-dev-skills winui-designwinui-search.exeSKILL.md.\winui-search.exe search "<feature 1>" "<feature 2>" ... # batch one focused query per feature (BM25 likes focused phrasing)
.\winui-search.exe get <id 1> <id 2> ... # batch up to 3 IDs — full XAML + C# + pitfall notes
.\winui-search.exe list # browse all patterns (heavy — prefer search)
.\winui-search.exe update # force cache refresh| App type | Anchor controls | Reference apps |
|---|---|---|
| Settings / config tool | | Windows Settings, Slack |
| Document / session editor | | Windows Terminal, VS Code, Notepad |
| Hierarchical browser | | File Explorer, Outlook |
| Developer tool / dashboard | | Dev Home, GitHub Desktop |
| Single-purpose utility | Mode switcher + compact grid | Calculator, Snipping Tool |
| Media / canvas / hero | | Photos, Spotify, Clipchamp |
DataGrid<select><input type=date>NavigationViewTabViewBreadcrumbBarSelectorBarListViewGridViewItemsRepeaterUniformGridLayoutTreeViewListViewGridItemTemplateGridDataGridCommunityToolkit.WinUI.Controls.DataGridx:BindListViewGridTextBoxNumberBoxAutoSuggestBoxCalendarDatePickerToggleSwitchRadioButtonsComboBoxContentDialogFlyoutMenuFlyoutTeachingTipInfoBarAppNotificationwinui-search.exeWinUI 3 has no. Without an explicit size, Windows defaults the main window to ~1024×768 — oversized for most utilities. Size it inSizeToContent's constructor.MainWindow
AppWindow.ResizeXamlRoot.RasterizationScaleAppWindow.Move[DllImport] GetDpiForWindowusing Microsoft.UI;
using Microsoft.UI.Windowing;
using System.Runtime.InteropServices;
using Windows.Graphics;
public sealed partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern uint GetDpiForWindow(IntPtr hWnd);
public MainWindow()
{
InitializeComponent();
var hwnd = Win32Interop.GetWindowFromWindowId(AppWindow.Id);
var scale = GetDpiForWindow(hwnd) / 96.0;
// widthDip / heightDip come from the rubric above — derive, don't copy.
AppWindow.Resize(new SizeInt32((int)(widthDip * scale), (int)(heightDip * scale)));
}
}WidthHeightGridx:BindOneTime<!-- ❌ silently never updates -->
<TextBlock Text="{x:Bind Vm.Status}" />
<!-- ✅ -->
<TextBlock Text="{x:Bind Vm.Status, Mode=OneWay}" />TextBoxUpdateSourceTrigger=PropertyChanged<TextBox Text="{x:Bind Vm.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />LostFocusTextBox.TextPropertyChangedSendKeysusing Microsoft.UI.Xaml.Automation;
// ❌ WRONG — does not compile. CS0117: 'Button' does not contain a definition for 'AutomationProperties'.
// AutomationProperties is a static class of attached-property accessors, not an instance member.
var btn = new Button { AutomationProperties = { AutomationId = "BtnSave" } };
// ✅ CORRECT
var btn = new Button { Content = "Save" };
AutomationProperties.SetAutomationId(btn, "BtnSave");
AutomationProperties.SetName(btn, "Save button");
Grid.SetRow(btn, 1);
ToolTipService.SetToolTip(btn, "Save the current document");Converter={x:Null}x:Bind{x:Bind}Converter{StaticResource}Converter={x:Null}LookupConverter("")Resource Dictionary Key can only be String-typedNullReferenceExceptionx:BindIValueConverter// MainPage.xaml.cs
public static Visibility BoolToVisibility(bool v) => v ? Visibility.Visible : Visibility.Collapsed;
public static Visibility InvertBoolToVisibility(bool v) => v ? Visibility.Collapsed : Visibility.Visible;
public static bool Not(bool v) => !v;<TextBlock Visibility="{x:Bind local:MainPage.BoolToVisibility(Vm.IsLoading), Mode=OneWay}" />
<Button IsEnabled="{x:Bind local:MainPage.Not(Vm.IsLoading), Mode=OneWay}" />ThemeShadowBackgroundSizingInnerBorderEdgeBorderControlOuterBorderEdgeThemeShadowTranslation1632128ThemeShadow.Receivers{ThemeResource ...}{StaticResource}ThemeDictionariesSystemAccentColorSystemColor*{ThemeResource}LightDarkHighContrastDefaultCardBackgroundBrushDangerTextBrushHighContrastAdjustment="None"| ❌ Don't | ✅ Do instead |
|---|---|
Reflexively build every app as | Pick the closest row in the silhouette table; hero / document / utility shapes are equally valid |
| Treat brand colour or tinted backdrop as off-pattern | Overriding |
| Tiny content island on an oversized window | Either size the window to the content (see Window sizing) or let content fill the available space |
| Custom pill / segmented tab switcher built by hand | |
| Equal-width 50/50 column split where one pane is structural | Stable size for the structural pane, flexible for content — only if a structural pane is part of the silhouette at all |
Hard-coded color literals ( | |
| The collection control already scrolls — give it a constrained height |
Custom | Built-in control + lightweight style overrides |
| Placeholder text used as the only field label | Always provide a visible label |
| Required commands hidden at small widths with no route | Overflow menu, secondary surface, or a responsive promotion rule |
Modal | |
| Destructive action (Delete / Discard / Reset) fired without confirmation | |
Custom list control when | Use the platform collection + virtualisation |
| File | Load when… |
|---|---|
| Looking up a brush key by purpose, picking between |
| Authoring theme dictionaries, custom brushes/styles/templates, or High Contrast support. |
| Reviewing responsive behaviour, breakpoints, or empty/loading/error coverage on a data-driven page. |