diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index 5ae5357b6..f90ce8960 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -73,6 +73,13 @@ Pages use the `ControlExample` custom control to show interactive demos:
2. Create a folder `Samples/{UniqueId}/` and add `{ControlName}Page.xaml` and `.xaml.cs` using the `ControlExample` pattern above. The folder name **must** match the `UniqueId` exactly.
3. The source generator auto-maps the `UniqueId` to the page type — no manual registration needed.
4. Add any code snippets as `.txt` files in the same `Samples/{UniqueId}/` folder. They are automatically included in the build as content.
+5. Regenerate the sample index and commit the result:
+
+```powershell
+dotnet run --project tools/CatalogExporter -- generate
+```
+
+`catalog/windows-samples.json` is a checked-in file that other tools consume, and CI fails if it does not match the current samples. Run this whenever you add, rename, remove, or edit a control page or a snippet `.txt`.
## Accessibility
diff --git a/.pipelines/azure-pipelines.yml b/.pipelines/azure-pipelines.yml
index c36e3d6b9..72209d6fc 100644
--- a/.pipelines/azure-pipelines.yml
+++ b/.pipelines/azure-pipelines.yml
@@ -24,6 +24,12 @@ steps:
feedsToUse: 'config'
nugetConfigPath: '$(System.DefaultWorkingDirectory)\nuget.config'
+ - task: DotNetCoreCLI@2
+ displayName: Verify catalog/windows-samples.json is up to date
+ inputs:
+ command: 'test'
+ projects: 'tests/WinUIGallery.CatalogExporter.Tests/WinUIGallery.CatalogExporter.Tests.csproj'
+
- task: PowerShell@2
displayName: Generate Test Signing Certificate
inputs:
diff --git a/WinUIGallery.slnx b/WinUIGallery.slnx
index 644b72718..8be678907 100644
--- a/WinUIGallery.slnx
+++ b/WinUIGallery.slnx
@@ -48,6 +48,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/SampleSupport/Data/ControlInfoData.json b/WinUIGallery/SampleSupport/Data/ControlInfoData.json
index 6ea10fcc9..4f6518be1 100644
--- a/WinUIGallery/SampleSupport/Data/ControlInfoData.json
+++ b/WinUIGallery/SampleSupport/Data/ControlInfoData.json
@@ -236,7 +236,13 @@
"Title": "XamlReader - API",
"Uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.markup.xamlreader"
}
- ]
+ ],
+ "Catalog": {
+ "Aliases": [
+ "repl",
+ "live xaml preview"
+ ]
+ }
}
]
},
@@ -1383,7 +1389,13 @@
"RepeatButton",
"HyperlinkButton",
"AppBarButton"
- ]
+ ],
+ "Catalog": {
+ "Aliases": [
+ "cta",
+ "call to action"
+ ]
+ }
},
{
"UniqueId": "DropDownButton",
@@ -2606,8 +2618,6 @@
}
],
"RelatedControls": [
- "Panel",
- "StackLayout",
"ItemsRepeater"
]
},
diff --git a/WinUIGallery/SampleSupport/Data/ControlInfoDataSchema.json b/WinUIGallery/SampleSupport/Data/ControlInfoDataSchema.json
index 8651990f7..1d74f36dd 100644
--- a/WinUIGallery/SampleSupport/Data/ControlInfoDataSchema.json
+++ b/WinUIGallery/SampleSupport/Data/ControlInfoDataSchema.json
@@ -103,6 +103,31 @@
},
"description": "Additional keywords used purely for search. If a search query matches one of these tags, this sample will be surfaced in the results even when the tag does not appear in the Title."
},
+ "Catalog": {
+ "type": "object",
+ "description": "Optional, opt-in overrides consumed only by tools/CatalogExporter when generating catalog/windows-samples.json. Everything here is additive/derivable metadata that the running gallery app itself never reads; omit this block entirely unless a sample genuinely needs to diverge from what the exporter can derive automatically from the fields above and the on-disk sample folder.",
+ "properties": {
+ "Exclude": {
+ "type": "boolean",
+ "default": false,
+ "description": "When true, this item is left out of the generated catalog manifest entirely (for example, a developer utility page rather than a genuine, documentable sample)."
+ },
+ "Aliases": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Additional search aliases that are useful for an external catalog/agent but too broad or noisy for the in-app search experience (which already uses Tags)."
+ },
+ "RelatedSamples": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "Extra related-sample references that point outside this repository, formatted as '{owner}/{repo}#{uniqueId}'. Used to extend (not replace) RelatedControls, which can only reference other items in this same file."
+ }
+ }
+ }
},
"required": [ "UniqueId", "Title"]
}
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccelerators.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccelerators.txt
new file mode 100644
index 000000000..33dfc9650
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccelerators.txt
@@ -0,0 +1,58 @@
+--- xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+--- c#
+private void MakeRedButton_Click(object sender, RoutedEventArgs e)
+{
+ ColorRectangle.Fill = new SolidColorBrush(Colors.Red);
+}
+private void MakeBlueButton_Click(object sender, RoutedEventArgs e)
+{
+ ColorRectangle.Fill = new SolidColorBrush(Colors.Blue);
+}
+private void MakeChartreuseButton_Click(object sender, RoutedEventArgs e)
+{
+ ColorRectangle.Fill = new SolidColorBrush(Colors.Chartreuse);
+}
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccessKeys.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccessKeys.txt
new file mode 100644
index 000000000..f9cfce2cc
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccessKeys.txt
@@ -0,0 +1,20 @@
+--- xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticArrowKeys.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticArrowKeys.txt
new file mode 100644
index 000000000..073850c62
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticArrowKeys.txt
@@ -0,0 +1,10 @@
+--- xaml
+
+
+ Red
+ Blue
+ Green
+ Yellow
+
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticTabOrder.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticTabOrder.txt
new file mode 100644
index 000000000..a87b08445
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticTabOrder.txt
@@ -0,0 +1,10 @@
+--- xaml
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualArrowKeys.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualArrowKeys.txt
new file mode 100644
index 000000000..4e0adf94f
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualArrowKeys.txt
@@ -0,0 +1,32 @@
+--- xaml
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualTabOrder.txt b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualTabOrder.txt
new file mode 100644
index 000000000..debf58457
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualTabOrder.txt
@@ -0,0 +1,29 @@
+--- xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml
index 725cb978e..08d4a1b75 100644
--- a/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml
+++ b/WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml
@@ -74,7 +74,7 @@
-
+
@@ -86,19 +86,6 @@
-
-
-<StackPanel Spacing="4">
- <Button Content="First" />
- <!-- Non-interactive controls should not be in the tab order -->
- <TextBlock Text="(not present)" />
- <Button Content="Second" />
- <!-- Disabled controls should not be in the tab order -->
- <Button Content="(not present)" IsEnabled="False" />
- <Button Content="Third" />
-</StackPanel>
-
-
-
+
@@ -173,38 +160,6 @@
IsTabStop="False" />
-
-
-<Grid RowSpacing="8" ColumnSpacing="8">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
- </Grid.ColumnDefinitions>
-
- <TextBlock Grid.Column="1" HorizontalAlignment="Center" Text="Column 1"/>
- <TextBlock Grid.Column="2" HorizontalAlignment="Center" Text="Column 2"/>
-
- <!--
- This example is a bit contrived, since you could fix the
- tab order by reordering the elements in the XAML, but
- sometimes that is not easy to do.
- -->
- <TextBlock Grid.Row="1" VerticalAlignment="Center" Text="Row 1"/>
- <Button Grid.Column="1" Grid.Row="1" Content="First stop" TabIndex="1" HorizontalAlignment="Stretch"/>
- <Button Grid.Column="2" Grid.Row="1" Content="Third stop" TabIndex="3" HorizontalAlignment="Stretch"/>
-
- <TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Row 2"/>
- <Button Grid.Column="1" Grid.Row="2" Content="Second stop" TabIndex="2" HorizontalAlignment="Stretch"/>
- <Button Grid.Column="2" Grid.Row="2" Content="Not a stop" IsTabStop="False" HorizontalAlignment="Stretch"/>
-</Grid>
-
-
-
+
@@ -261,19 +216,6 @@
-
-
-<!-- ListViews fully support arrow keys, for example -->
-<ListView
- Width="300"
- AutomationProperties.Name="Colors">
- <ListViewItem>Red</ListViewItem>
- <ListViewItem>Blue</ListViewItem>
- <ListViewItem>Green</ListViewItem>
- <ListViewItem>Yellow</ListViewItem>
-</ListView>
-
-
-
+
-
-
-<StackPanel
- Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
- BorderBrush="{ThemeResource SurfaceStrokeColorDefaultBrush}"
- AutomationProperties.Name="Potatoes?"
- BorderThickness="1"
- Spacing="8"
- Padding="8"
- CornerRadius="4">
- <TextBlock
- Style="{ThemeResource BodyStrongTextBlockStyle}"
- Text="Potatoes?" />
- <!--
- XYFocusKeyboardNavigation enables arrow keys between the buttons.
-
- Note that:
-
- - The buttons are still tabbable by default
- - Home/End and PgUp/PgDn do not work
- - Screen readers do not read PositionInSet/SizeOfSet ("1 of 3")
-
- All of that would require custom work.
- -->
- <StackPanel
- Spacing="4"
- Orientation="Horizontal"
- XYFocusKeyboardNavigation="Enabled">
- <Button Content="Boil 'em" />
- <Button Content="Mash 'em" />
- <Button Content="Stick 'em in a stew" />
- </StackPanel>
-</StackPanel>
-
-
-
+
@@ -481,70 +388,6 @@
-
-
-<Grid ColumnSpacing="8" RowSpacing="8">
-<Grid.RowDefinitions>
- <RowDefinition Height="Auto" />
- <RowDefinition Height="Auto" />
-</Grid.RowDefinitions>
-
-<Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="Auto"/>
-</Grid.ColumnDefinitions>
-
-<Rectangle x:Name="ColorRectangle" Fill="Red"
- Height="30" RadiusX="4" RadiusY="4"
- Grid.ColumnSpan="3"/>
-
-<Button Click="MakeRedButton_Click" Content="Red" Grid.Row="1"
- ToolTipService.ToolTip="Shortcut: Ctrl+R">
- <Button.KeyboardAccelerators>
- <KeyboardAccelerator Modifiers="Control" Key="R" />
- </Button.KeyboardAccelerators>
-</Button>
-
-<Button Click="MakeBlueButton_Click" Content="Blue"
- Grid.Row="1" Grid.Column="1"
- ToolTipService.ToolTip="Shortcut: Ctrl+B">
- <Button.KeyboardAccelerators>
- <KeyboardAccelerator Modifiers="Control" Key="B" />
- </Button.KeyboardAccelerators>
-</Button>
-
-<!--
- Chartreuse is an uncommon color, so we explain it in the tooltip.
- This replaces the auto-generated tooltip, so we manually mention
- the hotkey in the custom tooltip.
--->
-<Button Click="MakeChartreuseButton_Click" Content="Chartreuse"
- Grid.Row="1" Grid.Column="1"
- ToolTipService.ToolTip="A greenish yellow (Ctrl+G)">
- <Button.KeyboardAccelerators>
- <KeyboardAccelerator Modifiers="Control" Key="G" />
- </Button.KeyboardAccelerators>
-</Button>
-</Grid>
-
-
-
-
-private void MakeRedButton_Click(object sender, RoutedEventArgs e)
-{
- ColorRectangle.Fill = new SolidColorBrush(Colors.Red);
-}
-private void MakeBlueButton_Click(object sender, RoutedEventArgs e)
-{
- ColorRectangle.Fill = new SolidColorBrush(Colors.Blue);
-}
-private void MakeChartreuseButton_Click(object sender, RoutedEventArgs e)
-{
- ColorRectangle.Fill = new SolidColorBrush(Colors.Chartreuse);
-}
-
-
-
+
@@ -593,29 +436,6 @@ private void MakeChartreuseButton_Click(object sender, RoutedEventArgs e)
-
-
-<MenuBar>
- <MenuBarItem Title="File" AccessKey="F">
- <MenuFlyoutItem Text="New" AccessKey="N" />
- <MenuFlyoutItem Text="Open..." AccessKey="O" />
- <MenuFlyoutItem Text="Save" AccessKey="S" />
- <MenuFlyoutItem Text="Exit" AccessKey="E" />
- </MenuBarItem>
-
- <MenuBarItem Title="Edit" AccessKey="E">
- <MenuFlyoutItem Text="Undo" AccessKey="U" />
- <MenuFlyoutItem Text="Cut" AccessKey="X" />
- <MenuFlyoutItem Text="Copy" AccessKey="C" />
- <MenuFlyoutItem Text="Paste" AccessKey="V" />
- </MenuBarItem>
-
- <MenuBarItem Title="Help" AccessKey="H">
- <MenuFlyoutItem Text="About" AccessKey="A" />
- </MenuBarItem>
-</MenuBar>
-
-
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderControlGroups.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderControlGroups.txt
new file mode 100644
index 000000000..782df0adc
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderControlGroups.txt
@@ -0,0 +1,23 @@
+--- xaml
+
+
+
+
+
+ Trip to Redmond
+ Visiting Ben
+
+
+
+
+
+ Paul's winter vacation
+ Cool street photography
+ Valeria's cat
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderHeadings.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderHeadings.txt
new file mode 100644
index 000000000..3aa8fefa0
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderHeadings.txt
@@ -0,0 +1,23 @@
+--- xaml
+
+
+Lorem ipsums
+
+Lorem ipsum
+Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+ Pellentesque feugiat velit pulvinar, vehicula nisi at, molestie risus.
+ Duis consequat auctor libero vitae consectetur. Nullam efficitur euismod lacinia.
+
+Cat ipsum
+
+Standard
+Mice litter kitter kitty litty little kitten big roar roar feed me
+ but i will ruin the couch with my claws and hunt by meowing loudly at 5am next to human.
+Cat breeds
+Tabby abyssinian for jaguar. Thai russian blue and ragdoll, ocicat.
+ Mouser puma so american bobtail for donskoy balinese . Scottish fold manx so siamese.
+
+Bacon ipsum
+Bacon ipsum dolor amet meatball nulla labore,
+ tempor sirloin chicken frankfurter tail drumstick ex cupim ground round.
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLabeledBy.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLabeledBy.txt
new file mode 100644
index 000000000..dbf383643
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLabeledBy.txt
@@ -0,0 +1,3 @@
+--- xaml
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLandmarks.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLandmarks.txt
new file mode 100644
index 000000000..0cee09e22
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLandmarks.txt
@@ -0,0 +1,54 @@
+--- xaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
+ Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
+
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromContent.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromContent.txt
new file mode 100644
index 000000000..08c9d83cc
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromContent.txt
@@ -0,0 +1,3 @@
+--- xaml
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromHeader.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromHeader.txt
new file mode 100644
index 000000000..4b0a30eff
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromHeader.txt
@@ -0,0 +1,9 @@
+--- xaml
+
+
+
+
+
+
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnImage.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnImage.txt
new file mode 100644
index 000000000..f6d350cea
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnImage.txt
@@ -0,0 +1,3 @@
+--- xaml
+
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnListView.txt b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnListView.txt
new file mode 100644
index 000000000..ab70e12b8
--- /dev/null
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnListView.txt
@@ -0,0 +1,9 @@
+--- xaml
+
+
+Nathan Quinn
+Jessica Lamber
+Carl Bond
+Jessica Russel
+
diff --git a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml
index 07ad78602..0b839ffb5 100644
--- a/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml
+++ b/WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml
@@ -82,7 +82,7 @@
-
+
@@ -93,15 +93,9 @@
-
-
-<!-- Most controls automatically get names from their content -->
-<Button Content="Download survey" />
-
-
-
+
@@ -135,18 +129,6 @@
-
-
-<!-- Headers are promoted to name -->
-<TextBox Header="Name" />
-
-<!-- As are placeholders -->
-<TextBox PlaceholderText="Nickname" />
-
-<!-- If both are provided, headers are name and placeholders are moved to description -->
-<TextBox Header="Email" PlaceholderText="test@example.com" MinWidth="200" />
-
-
@@ -162,7 +144,7 @@
-
+
-
-
-<!-- Add a name to this ListView to be heard when screen reader users enter it -->
-<ListView Width="300"
-AutomationProperties.Name="Contacts">
-<ListViewItem>Nathan Quinn</ListViewItem>
-<ListViewItem>Jessica Lamber</ListViewItem>
-<ListViewItem>Carl Bond</ListViewItem>
-<ListViewItem>Jessica Russel</ListViewItem>
-</ListView>
-
-
-
+
@@ -215,12 +185,6 @@ AutomationProperties.Name="Contacts">
-
-
-<!-- Add "alt text" to this image so screen reader users can understand it -->
-<Image AutomationProperties.Name="Grapes" Source="ms-appx:///Assets/SampleMedia/grapes.jpg"/>
-
-
@@ -236,7 +200,7 @@ AutomationProperties.Name="Contacts">
below), to avoid being redundant.
-
+
-
-
-<TextBlock x:Name="InputLabel" AutomationProperties.AccessibilityView="Raw" Text="Searching Photos:"/>
-<TextBox AutomationProperties.LabeledBy="{x:Bind InputLabel}"/>
-
-
@@ -427,7 +385,7 @@ AutomationProperties.Name="Contacts">
typically identify big sections of your UI, like "search", "main content", or "navigation." You can also add landmarks with custom names.
-
+
-
-
-<Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="200" />
- <ColumnDefinition Width="*" />
- <ColumnDefinition Width="200" />
- </Grid.ColumnDefinitions>
-
- <!-- The navigation pane for our app -->
- <StackPanel
- Grid.Column="0"
- Spacing="8"
- Padding="6"
- Background="{ThemeResource CardStrokeColorDefaultBrush}"
- CornerRadius="{StaticResource ControlCornerRadius}"
- AutomationProperties.LandmarkType="Navigation">
- <AutoSuggestBox
- PlaceholderText="Search"
- AutomationProperties.LandmarkType="Search"/>
- <Button Content="Open settings" />
- </StackPanel>
-
- <!-- The main content of our app -->
- <StackPanel
- Grid.Column="1"
- Padding="6"
- AutomationProperties.LandmarkType="Main">
- <TextBlock TextWrapping="WrapWholeWords">
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
- Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
- Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
- Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum
- </TextBlock>
- </StackPanel>
-
- <!-- A custom sidebar with a custom landmark name -->
- <StackPanel
- Grid.Column="2"
- Padding="6"
- Background="{ThemeResource CardStrokeColorDefaultBrush}"
- CornerRadius="{StaticResource ControlCornerRadius}"
- Spacing="8"
- AutomationProperties.LandmarkType="Custom"
- AutomationProperties.LocalizedLandmarkType="Current viewers">
- <TextBlock
- Text="Current viewers"
- Style="{ThemeResource BodyStrongTextBlockStyle}"
- AutomationProperties.HeadingLevel="Level1" />
- <TextBlock
- Text="(No other users viewing)"
- Style="{ThemeResource BodyTextBlockStyle}"
- FontStyle="Italic" />
- </StackPanel>
-</Grid>
-
-
-
+
-
-
-<StackPanel MaxWidth="500">
-<!-- Here is the main header for the whole text. It gets HeadingLevel 1 -->
-<TextBlock AutomationProperties.HeadingLevel="Level1" FontSize="26">Lorem ipsums</TextBlock>
-<!-- The following TextBlock is the header for the standard lorem ipsum text, thus it is only HeadingLevel 2-->
-<TextBlock AutomationProperties.HeadingLevel="Level2" FontSize="22">Lorem ipsum</TextBlock>
-<TextBlock TextWrapping="WrapWholeWords">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
- Pellentesque feugiat velit pulvinar, vehicula nisi at, molestie risus.
- Duis consequat auctor libero vitae consectetur. Nullam efficitur euismod lacinia.</TextBlock>
-
-<TextBlock AutomationProperties.HeadingLevel="Level2" FontSize="22">Cat ipsum</TextBlock>
-<!-- This is the header for the standard cat ipsum section, which is hierarchically below the cat ipsum header, resulting in HeadingLevel 3 -->
-<TextBlock AutomationProperties.HeadingLevel="3" FontSize="18">Standard</TextBlock>
-<TextBlock TextWrapping="WrapWholeWords">Mice litter kitter kitty litty little kitten big roar roar feed me
- but i will ruin the couch with my claws and hunt by meowing loudly at 5am next to human.</TextBlock>
-<TextBlock AutomationProperties.HeadingLevel="3" FontSize="18">Cat breeds</TextBlock>
-<TextBlock TextWrapping="WrapWholeWords">Tabby abyssinian for jaguar. Thai russian blue and ragdoll, ocicat.
- Mouser puma so american bobtail for donskoy balinese . Scottish fold manx so siamese.</TextBlock>
-
-<TextBlock AutomationProperties.HeadingLevel="2" FontSize="22">Bacon ipsum</TextBlock>
-<TextBlock TextWrapping="WrapWholeWords">Bacon ipsum dolor amet meatball nulla labore,
- tempor sirloin chicken frankfurter tail drumstick ex cupim ground round.</TextBlock>
-</StackPanel>
-
-
-
+
@@ -691,32 +566,6 @@ AutomationProperties.Name="Contacts">
-
-
-<StackPanel AutomationProperties.Name="Album browser">
- <StackPanel AutomationProperties.Name="My albums">
- <!-- These TextBlocks could reasonably be headings, too. -->
- <TextBlock
- Text="My albums"
- Style="{ThemeResource BodyStrongTextBlockStyle}" />
- <ListView>
- <x:String>Trip to Redmond</x:String>
- <x:String>Visiting Ben</x:String>
- </ListView>
- </StackPanel>
- <StackPanel AutomationProperties.Name="Shared with me">
- <TextBlock
- Text="Shared with me"
- Style="{ThemeResource BodyStrongTextBlockStyle}" />
- <ListView>
- <x:String>Paul's winter vacation</x:String>
- <x:String>Cool street photography</x:String>
- <x:String>Valeria's cat</x:String>
- </ListView>
- </StackPanel>
-</StackPanel>
-
-
diff --git a/catalog/README.md b/catalog/README.md
new file mode 100644
index 000000000..8b378edd3
--- /dev/null
+++ b/catalog/README.md
@@ -0,0 +1,147 @@
+# WinUI Gallery sample index
+
+`catalog/windows-samples.json` is a generated, machine-readable index of every embedded sample in this repository, including the XAML and C# the gallery shows for each one. It exists so that tools and agents can discover and reuse WinUI Gallery's samples without scraping the app's XAML.
+
+## The shape is a shared contract, not ours
+
+The file conforms to the **WinUI sample index** contract published by [microsoft/winappCli](https://github.com/microsoft/winappCli) at [`docs/winui-sample-index.schema.json`](https://raw.githubusercontent.com/microsoft/winappCli/main/docs/winui-sample-index.schema.json), which the generated file names in its own `$schema` property.
+
+That contract already has a working consumer and a second publisher ([microsoft-ui-reactor](https://github.com/microsoft/microsoft-ui-reactor) publishes a conforming index today), so emitting it directly means a tool that already reads one source can read this one with no new parser and no gallery-specific special cases. The alternative — inventing a gallery-shaped file and asking every consumer to adapt to it — would have produced the same data behind a second, redundant contract.
+
+Two consequences of the contract are worth knowing before reading the file:
+
+- **Code is inline.** The contract is explicitly designed so a consumer needs *one* HTTP request rather than one per snippet, so each sample carries its `xaml` and `code` directly instead of pointing at a file to fetch separately.
+- **Sample order is meaningful.** Consumers number a control's samples positionally. Samples are therefore emitted in page order — the order a visitor sees them — so appending a `ControlExample` is safe while reordering renumbers the ones after it.
+
+Fields the contract has no slot for are grouped under a `gallery` object on each control and sample, rather than scattered among the shared ones, so it stays obvious which is which. The contract permits these extras and consumers ignore them.
+
+## Why this, and not one `sample.yml` per control
+
+`windows-samples` normally has one `Samples//sample.yml` per **standalone** project. WinUI Gallery is different: its ~120 samples are **pages embedded in a single app** (`WinUIGallery/Samples//`), and the authoritative inventory of them already exists as [`WinUIGallery/SampleSupport/Data/ControlInfoData.json`](../WinUIGallery/SampleSupport/Data/ControlInfoData.json), consumed by the app itself and by `WinUIGallery.SourceGenerator` at build time.
+
+Adding ~120 hand-maintained `sample.yml` files would create a second, easily-stale source of truth. Instead:
+
+- **`ControlInfoData.json` stays the single source of truth.** It already carries most of what an index needs: `Title`, `Subtitle`/`Description`, `Docs`, `Tags`, and `RelatedControls`.
+- **`tools/CatalogExporter`** deterministically derives everything else — ids, source paths, scenarios, and the code itself — from that JSON file plus the on-disk sample folders, and validates the result.
+
+## Regenerating and checking the index
+
+```powershell
+# Regenerate the index from the current source data
+dotnet run --project tools/CatalogExporter -- generate
+
+# Verify the committed file is still up to date (used in CI/tests); does not write anything
+dotnet run --project tools/CatalogExporter -- check
+```
+
+Both commands auto-detect the repository root by walking up to `WinUIGallery.slnx`; pass `--repo-root ` to override.
+
+`tests/WinUIGallery.CatalogExporter.Tests` asserts the committed file matches a fresh `generate`, so a stale or hand-edited index fails `dotnet test` (and therefore CI) rather than silently drifting from `ControlInfoData.json`. `ContractConformanceTests` additionally checks the parts a consumer depends on that valid JSON alone would not catch — that every emitted field name is one the contract defines, that required fields are present, that control ids are unique and URL-safe, and that every published XAML fragment parses.
+
+The index deliberately carries **no generation timestamp**, even though the contract offers `generatedAtUtc`. The file is committed and CI regenerates it to prove it is current; a timestamp would make every run differ and turn that check into constant churn.
+
+### Adding a type the serializer touches
+
+JSON goes through source-generated metadata, matching the gallery app and the navigation source generator, which both define a `JsonSerializerContext` for this same `ControlInfoData.json`. `CatalogReadContext` covers the input and `CatalogWriteContext` the output, both in `CatalogJsonContext.cs`.
+
+Reflection-based serialization is switched off in both projects, so this is enforced rather than conventional: **a type the serializer reaches that no context covers throws at runtime instead of quietly falling back.** If you add a new serialized type and see `Reflection-based serialization has been disabled for this application`, the fix is a `[JsonSerializable(typeof(YourType))]` on the relevant context, not a change to the options.
+
+Serializer behaviour — the camelCase naming policy, indentation, and null omission — stays on `CatalogGenerator.ReadOptions` and `WriteOptions` rather than on `JsonSourceGenerationOptions` attributes, so there is a single definition of it. `WriteOptions` decides the published field names and `ContractConformanceTests` derives the names it expects from that same object, which is what lets the test verify the writer instead of a second copy of the writer's configuration.
+
+## How source data maps onto the contract
+
+| Contract field | Derived from |
+| --- | --- |
+| `source` | Fixed as `"gallery"` — the identifier the consumer already uses for this repository |
+| `controls[].id` | The lowercased `UniqueId`. The contract scopes ids to a source, so `"button"` is unambiguous without repeating the repository in it |
+| `controls[].name`, `.description`, `.details`, `.apiNamespace`, `.docs` | `Title`, `Subtitle`, `Description`, `ApiNamespace`, `Docs` on the matching `ControlInfoData.json` item |
+| `controls[].relatedControls` | `RelatedControls`, as display names — the contract asks for names here, not ids |
+| `controls[].curatedKeywords` | `Tags` plus any `Catalog.Aliases`. Both are written by the sample's own author, and the contract has one slot for author-written terms, which consumers weigh above derived ones |
+| `controls[].keywords` | `BaseClasses`, as supplementary derived search terms |
+| `controls[].xmlnsImports` | The namespace declarations the control's samples actually use, resolved against its page's own `xmlns` attributes, plus any the fragment declares on itself. Hoisted here only when every sample needs the same set; otherwise each sample carries its own. A prefix nothing declares — a snippet using `local:` to mean "your namespace" — is never invented, since a guessed URI would look authoritative and not compile; the fragment is omitted instead, because an incomplete import list produces XAML that does not bind on arrival |
+| `controls[].samples[]` | One entry per `controls:ControlExample` whose `SampleDefinition="..."` names a snippet file that exists next to the page, in page order |
+| `controls[].samples[].header` | The snippet's `--- header` section, as shown above the scenario in the app; falls back to a name derived from the snippet file name |
+| `controls[].samples[].xaml`, `.code` | The snippet's `--- xaml` and `--- c#` sections, with `$(Token)` placeholders resolved. `xaml` is guaranteed to contain no leftover token; `code` may still carry one that was not safe to remove |
+| `controls[].samples[].language` | `"csharp"` whenever `code` is present; the only value contract version 1 accepts |
+| `controls[].samples[].gallery.codePlaceholdersPresent` | The `$(Token)` names still present in `code`, in order of first appearance; omitted entirely when there are none. The mirror image of `gallery.xamlPlaceholdersDropped`, not a companion to it: that field names tokens that were *removed*, this one names tokens that are *still there*, so a sample carrying it is not pasteable as published |
+| `controls[].samples[].gallery.xamlOmittedUnboundPrefixes` | The namespace prefixes that cost a sample its XAML: the snippet binds them, but neither its page nor the fragment itself declares them, so no import could be published and the markup would not bind wherever it was pasted |
+| `controls[].gallery`, `samples[].gallery` | Gallery-specific provenance: `uniqueId`, `group`, page and snippet paths, badges, base classes, and source-qualified related-sample ids |
+
+### Snippet bundles, and staying faithful to what the app renders
+
+A `SampleDefinition` snippet is a small sectioned text file:
+
+```text
+--- header
+Built-in styles applied to Button.
+--- xaml
+
+```
+
+The exporter parses these with `SampleBundleParser`, which deliberately mirrors `ControlExample.ParseSampleCodeSections` in [`WinUIGallery/Controls/ControlExample.xaml.cs`](../WinUIGallery/Controls/ControlExample.xaml.cs) — the source of truth for the format. The index's promise is "this is the code the gallery shows for this scenario", so if the two parsers diverge it silently publishes something users never see. `SampleBundleParserTests` pins the rules that are easiest to get subtly wrong: the marker is `"--- "` including the trailing space, section content is trimmed, and unknown sections are ignored. **Keep the two parsers in sync.**
+
+Every scenario supplies its code this way. That is enforced, not merely conventional: `RealRepository_NoSampleUsesInlineControlExampleCode` fails if any page reintroduces inline `` or `` markup. Inline code renders correctly in the gallery but is invisible to the exporter, so it would otherwise go missing from the index with no visible symptom.
+
+### `$(Token)` placeholders
+
+A page can pair a snippet with `ControlExampleSubstitution` entries that bind a token to one of the interactive option controls, so the code updates as the reader changes a slider or a dropdown. Published verbatim, a token like `$(Spacing)` would leave the snippet impossible to paste into a project — and a token that stands in for a whole attribute, such as `$(IsEnabled)`, would leave the XAML unparseable and therefore discarded entirely.
+
+The exporter resolves each token to the value its control starts with, which is exactly what the gallery renders when the page first loads. Resolution is deliberately conservative and reads only what the markup actually states: a literal `Value`, an initial attribute on the bound control, the item a selector explicitly marks as selected, or a gate on a boolean whose documented default is false (`IsChecked`, `IsOn`, `IsSticky`, `IsOpen`) that the markup never sets. That last rule is an explicit short list rather than a general "unset means false", because `IsEnabled`, `IsTabStop` and `IsHitTestVisible` all default to *true* and a blanket rule would invert them.
+
+Some tokens cannot be settled from markup alone — a converter function such as `BoolToLowerString(x.IsOn)`, a selector populated from code-behind, or a control that declares no initial value and relies on a framework default the exporter does not know. The exporter never guesses one, because publishing a value the gallery does not show would be worse than publishing none.
+
+XAML instead degrades by deletion. `TokenFallback` removes the whole attribute carrying an unresolvable token, which leaves that property at its own default — in the common case, where the token binds the demo control's own property, that is precisely the value the reader sees when the page first loads. A token standing in for a whole attribute, such as `$(IsEnabled)`, is removed the same way. The fragment stays well-formed and pasteable, and the names that were dropped are listed in `gallery.xamlPlaceholdersDropped` so the loss is visible rather than silent. `CatalogGenerator` re-checks each fragment afterwards and fails the build if a token survived, so a published `xaml` value never contains `$(`; `RealRepository_NoPublishedXamlContainsAPlaceholder` pins that guarantee.
+
+`code` cannot degrade the same way, and that asymmetry is a property of the language rather than unfinished work. Deleting a XAML attribute works because the property then falls back to its own default; C# has no construct whose absence yields a default. The tokens that actually occur bear this out: they appear as identifier fragments (`BadgeNotificationGlyph.$(SelectedGlyph)`), as arguments in a fixed-arity call (`SetBorderAndTitleBar($(HasBorder), $(HasTitleBar))`), and as whole statements (`$(TxtFileType)$(JsonFileType)`). Removing any of those leaves either code that does not compile or a sample with its subject cut out. Inferring a value instead would be worse than publishing none, for the reason the resolver already refuses to guess: a `Slider` whose `Minimum` is above zero silently coerces whatever it is handed, and several of these tokens are bound to controls a constructor initializes, so a markup-derived guess would state a value the gallery never shows.
+
+So C# tokens are published verbatim, and the exporter declares that rather than leaving it to be discovered. `gallery.codePlaceholdersPresent` lists the token names a sample's `code` still contains, and is omitted when there are none. **Read the two placeholder fields as opposites.** `xamlPlaceholdersDropped` is a record of cleanup already done — the tokens are gone and the fragment pastes as published. `codePlaceholdersPresent` is a warning about cleanup that is not possible — the tokens are still in the string and the code will not compile as published. A consumer that conflates them pastes broken C#, which is precisely what the field exists to prevent. Treat `code` as templated whenever it is present, and use the sample's page as the reference for real values: the gallery resolves these tokens at runtime from the live option controls.
+
+A substitution whose `IsEnabled` resolves to false becomes the empty string, matching `ControlExampleSubstitution.ValueAsString`. Literal values keep their surrounding whitespace, because some snippets rely on a value such as `` IsSticky="True" `` to supply its own separating spaces.
+
+`SubstitutionResolverTests` pins these rules, and several of its cases assert that an ambiguous binding is skipped rather than guessed.
+
+### Samples that carry no XAML, and scenarios that are left out
+
+The contract requires a sample to carry XAML or code, and its consumer skips any that has neither. Two situations are handled explicitly.
+
+**A scenario with no code at all is omitted from the index.** This happens when a page sets `SourceCodeVisibility="Collapsed"`, so the gallery deliberately shows no code, or when a page swaps `ControlExample.XamlSource` at runtime and no single snippet represents the scenario.
+
+**A snippet whose XAML is not a well-formed fragment keeps its C# and loses its XAML.** Several snippets are written for the gallery's own code viewer, where a human correctly reads `` as "your existing window". That is not parseable XML, and a consumer parses each fragment and discards whatever fails *without reporting it* — so publishing it would advertise code that never arrives. The exporter omits the XAML instead, prints a warning during `generate`, and marks the sample with `gallery.xamlOmittedAsMalformed` so the omission is visible rather than looking like a sample that simply has no XAML.
+
+**A snippet that binds a namespace prefix nothing declares also loses its XAML.** A fragment using `local:`, `common:`, `l:` or `data:` to name a type that lives in the gallery's own app is not portable: the prefix resolves against neither its page's `xmlns` attributes nor its own, so there is no import to publish, and a guessed URI would be worse than none. Well-formedness cannot catch this — the exporter and the consumer both synthesize a declaration for every prefix they encounter, deliberately, so that the two agree — which means such a fragment parses cleanly on both sides and fails only at the moment a reader pastes it alongside the imports this index handed them. The XAML is therefore omitted and the offending prefixes are listed in `gallery.xamlOmittedUnboundPrefixes`. `RealRepository_EveryPublishedFragmentDeclaresThePrefixesItUses` asserts the resulting guarantee as a property: every published fragment declares, or is published with an import for, every prefix it binds.
+
+A snippet that declares its own prefix, such as ``, is self-contained and is published unchanged — it needs nothing from its page and nothing from the import list.
+
+Two samples carry no C# and so leave the index entirely rather than merely losing their XAML: `FlipView/FlipviewShowingBoundData.txt` and `ItemsRepeater/LayingOutNestedItemsrepeaters.txt`. That cost is accepted deliberately, because both were only ever publishable as markup a consumer could not compile.
+
+`RealRepository_SnippetsWithUnpublishableXamlAreTheKnownSet` pins the current set, so a newly broken snippet surfaces as a test failure instead of quietly disappearing. All but two still publish their C#; the exceptions are named above.
+
+### The optional `Catalog` override block
+
+`ControlInfoData.json` items may include an optional `Catalog` object (see `ControlInfoDataSchema.json`) for the rare case where the exporter can't safely derive something on its own:
+
+```jsonc
+"Catalog": {
+ "Exclude": false, // drop this item from the index entirely
+ "Aliases": [ "cta" ], // extra author-written search keywords, additive to Tags
+ "RelatedSamples": [ "owner/other-repo#sample-id" ] // cross-repository related samples
+}
+```
+
+This block is read only by `tools/CatalogExporter` — the running gallery app never looks at it — and is expected to stay rare. `Button` and `ScratchPad` in `ControlInfoData.json` each set `Catalog.Aliases` as a small, working example of the mechanism.
+
+### Inclusion and exclusion rules
+
+An item from `ControlInfoData.json` becomes a control in the index when, and only when:
+
+1. It has a non-empty `UniqueId` that is unique across the file.
+2. A `WinUIGallery/Samples//` folder exists with a case-exact `Page.xaml` file in it.
+3. It does not set `Catalog.Exclude: true`.
+
+Anything else — a missing folder or page, a duplicate id, a `RelatedControls`/`Catalog.RelatedSamples` reference that doesn't resolve to an included entry, a `SampleDefinition` that is not written as `\.txt` or names a snippet that doesn't exist on disk, or two `ControlExample` elements pointing at the same snippet — fails validation (`CatalogValidationException`) rather than being silently skipped or guessed at. All 120 current `ControlInfoData.json` items satisfy these rules.
+
+`SampleDefinition` is checked as a whole path, not just a file name, because `ControlExample` resolves it as `Samples/` at runtime. A value naming the wrong folder would otherwise pass here whenever a file of that name happened to sit next to the page, and fail only in the running app, as a scenario with an empty code viewer.
+
+### What's intentionally left out
+
+Optional fields are omitted rather than filled with guesses: `description`, `apiNamespace`, `docs`, `relatedControls` and the rest are absent when the source data has nothing to report. The index does not pin a commit SHA — it reflects the repository's default branch and is regenerated whenever samples change.
diff --git a/catalog/windows-samples.json b/catalog/windows-samples.json
new file mode 100644
index 000000000..be21bd658
--- /dev/null
+++ b/catalog/windows-samples.json
@@ -0,0 +1,10641 @@
+{
+ "$schema": "https://raw.githubusercontent.com/microsoft/winappCli/main/docs/winui-sample-index.schema.json",
+ "schemaVersion": 1,
+ "source": "gallery",
+ "generator": {
+ "tool": "tools/CatalogExporter",
+ "command": "dotnet run --project tools/CatalogExporter -- generate",
+ "repository": "https://github.com/microsoft/WinUI-Gallery",
+ "defaultBranch": "main",
+ "license": "MIT"
+ },
+ "controlCount": 123,
+ "controls": [
+ {
+ "id": "accessibilitycolorcontrast",
+ "name": "Color Contrast",
+ "description": "High contrast design ensures accessibility for all users.",
+ "curatedKeywords": [
+ "high contrast",
+ "WCAG",
+ "accessibility"
+ ],
+ "docs": [
+ {
+ "title": "Accessibility",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessibility"
+ },
+ {
+ "title": "Automation Properties - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.automation.automationproperties"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AccessibilityColorContrast",
+ "group": {
+ "id": "AccessibilityItem",
+ "title": "Accessibility"
+ },
+ "page": "WinUIGallery/Samples/AccessibilityColorContrast/AccessibilityColorContrastPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AccessibilityColorContrast/AccessibilityColorContrastPage.xaml.cs"
+ },
+ "samples": []
+ },
+ {
+ "id": "accessibilitykeyboard",
+ "name": "Keyboard Navigation",
+ "description": "Keyboard-friendly design enables seamless interactions.",
+ "usings": [
+ "Microsoft.UI",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media"
+ ],
+ "curatedKeywords": [
+ "keyboard",
+ "tab navigation",
+ "access keys",
+ "focus",
+ "accessibility"
+ ],
+ "docs": [
+ {
+ "title": "Accessibility",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessibility"
+ },
+ {
+ "title": "Accessibility overview",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessibility-overview"
+ },
+ {
+ "title": "Keyboard accessibility",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/keyboard-accessibility"
+ },
+ {
+ "title": "Keyboard interactions",
+ "uri": "https://learn.microsoft.com/windows/apps/design/input/keyboard-interactions"
+ },
+ {
+ "title": "Access keys",
+ "uri": "https://learn.microsoft.com/windows/apps/design/input/access-keys"
+ },
+ {
+ "title": "Keyboard accelerators",
+ "uri": "https://learn.microsoft.com/windows/apps/design/input/keyboard-accelerators"
+ },
+ {
+ "title": "Focus navigation for keyboard, gamepad, remote control, and accessibility tools",
+ "uri": "https://learn.microsoft.com/windows/apps/design/input/focus-navigation"
+ },
+ {
+ "title": "Automation Properties - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.automation.automationproperties"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AccessibilityKeyboard",
+ "group": {
+ "id": "AccessibilityItem",
+ "title": "Accessibility"
+ },
+ "page": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardPage.xaml.cs"
+ },
+ "samples": [
+ {
+ "header": "Automatic Tab Order",
+ "xaml": "\u003CStackPanel Spacing=\u00224\u0022\u003E\n \u003CButton Content=\u0022First\u0022 /\u003E\n \u003C!-- Non-interactive controls should not be in the tab order --\u003E\n \u003CTextBlock Text=\u0022(not present)\u0022 /\u003E\n \u003CButton Content=\u0022Second\u0022 /\u003E\n \u003C!-- Disabled controls should not be in the tab order --\u003E\n \u003CButton Content=\u0022(not present)\u0022 IsEnabled=\u0022False\u0022 /\u003E\n \u003CButton Content=\u0022Third\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardAutomaticTabOrder.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticTabOrder.txt",
+ "name": "Automatic Tab Order"
+ }
+ },
+ {
+ "header": "Manual Tab Order",
+ "xaml": "\u003CGrid RowSpacing=\u00228\u0022 ColumnSpacing=\u00228\u0022\u003E\n \u003CGrid.RowDefinitions\u003E\n\t \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n\t \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n\t \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CGrid.ColumnDefinitions\u003E\n\t \u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n\t \u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n\t \u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n\n \u003CTextBlock Grid.Column=\u00221\u0022 HorizontalAlignment=\u0022Center\u0022 Text=\u0022Column 1\u0022/\u003E\n \u003CTextBlock Grid.Column=\u00222\u0022 HorizontalAlignment=\u0022Center\u0022 Text=\u0022Column 2\u0022/\u003E\n\n \u003C!--\n This example is a bit contrived, since you could fix the\n tab order by reordering the elements in the XAML, but\n sometimes that is not easy to do.\n --\u003E\n \u003CTextBlock Grid.Row=\u00221\u0022 VerticalAlignment=\u0022Center\u0022 Text=\u0022Row 1\u0022/\u003E\n \u003CButton Grid.Column=\u00221\u0022 Grid.Row=\u00221\u0022 Content=\u0022First stop\u0022 TabIndex=\u00221\u0022 HorizontalAlignment=\u0022Stretch\u0022/\u003E\n \u003CButton Grid.Column=\u00222\u0022 Grid.Row=\u00221\u0022 Content=\u0022Third stop\u0022 TabIndex=\u00223\u0022 HorizontalAlignment=\u0022Stretch\u0022/\u003E\n\n \u003CTextBlock Grid.Row=\u00222\u0022 VerticalAlignment=\u0022Center\u0022 Text=\u0022Row 2\u0022/\u003E\n \u003CButton Grid.Column=\u00221\u0022 Grid.Row=\u00222\u0022 Content=\u0022Second stop\u0022 TabIndex=\u00222\u0022 HorizontalAlignment=\u0022Stretch\u0022/\u003E\n \u003CButton Grid.Column=\u00222\u0022 Grid.Row=\u00222\u0022 Content=\u0022Not a stop\u0022 IsTabStop=\u0022False\u0022 HorizontalAlignment=\u0022Stretch\u0022/\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardManualTabOrder.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualTabOrder.txt",
+ "name": "Manual Tab Order"
+ }
+ },
+ {
+ "header": "Automatic Arrow Keys",
+ "xaml": "\u003C!-- ListViews fully support arrow keys, for example --\u003E\n\u003CListView\n Width=\u0022300\u0022\n AutomationProperties.Name=\u0022Colors\u0022\u003E\n \u003CListViewItem\u003ERed\u003C/ListViewItem\u003E\n \u003CListViewItem\u003EBlue\u003C/ListViewItem\u003E\n \u003CListViewItem\u003EGreen\u003C/ListViewItem\u003E\n \u003CListViewItem\u003EYellow\u003C/ListViewItem\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardAutomaticArrowKeys.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAutomaticArrowKeys.txt",
+ "name": "Automatic Arrow Keys"
+ }
+ },
+ {
+ "header": "Manual Arrow Keys",
+ "xaml": "\u003CStackPanel\n Background=\u0022{ThemeResource CardBackgroundFillColorSecondaryBrush}\u0022\n BorderBrush=\u0022{ThemeResource SurfaceStrokeColorDefaultBrush}\u0022\n AutomationProperties.Name=\u0022Potatoes?\u0022\n BorderThickness=\u00221\u0022\n Spacing=\u00228\u0022\n Padding=\u00228\u0022\n CornerRadius=\u00224\u0022\u003E\n \u003CTextBlock\n Style=\u0022{ThemeResource BodyStrongTextBlockStyle}\u0022\n Text=\u0022Potatoes?\u0022 /\u003E\n \u003C!--\n XYFocusKeyboardNavigation enables arrow keys between the buttons.\n\n Note that:\n\n - The buttons are still tabbable by default\n - Home/End and PgUp/PgDn do not work\n - Screen readers do not read PositionInSet/SizeOfSet (\u00221 of 3\u0022)\n\n All of that would require custom work.\n --\u003E\n \u003CStackPanel\n Spacing=\u00224\u0022\n Orientation=\u0022Horizontal\u0022\n XYFocusKeyboardNavigation=\u0022Enabled\u0022\u003E\n \u003CButton Content=\u0022Boil \u0027em\u0022 /\u003E\n \u003CButton Content=\u0022Mash \u0027em\u0022 /\u003E\n \u003CButton Content=\u0022Stick \u0027em in a stew\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardManualArrowKeys.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardManualArrowKeys.txt",
+ "name": "Manual Arrow Keys"
+ }
+ },
+ {
+ "header": "Accelerators",
+ "xaml": "\u003CGrid ColumnSpacing=\u00228\u0022 RowSpacing=\u00228\u0022\u003E\n\u003CGrid.RowDefinitions\u003E\n\t\u003CRowDefinition Height=\u0022Auto\u0022 /\u003E\n\t\u003CRowDefinition Height=\u0022Auto\u0022 /\u003E\n\u003C/Grid.RowDefinitions\u003E\n\n\u003CGrid.ColumnDefinitions\u003E\n\t\u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n\t\u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n\t\u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n\u003C/Grid.ColumnDefinitions\u003E\n\n\u003CRectangle x:Name=\u0022ColorRectangle\u0022 Fill=\u0022Red\u0022\n\tHeight=\u002230\u0022 RadiusX=\u00224\u0022 RadiusY=\u00224\u0022\n\tGrid.ColumnSpan=\u00223\u0022/\u003E\n\n\u003CButton Click=\u0022MakeRedButton_Click\u0022 Content=\u0022Red\u0022 Grid.Row=\u00221\u0022\n\tToolTipService.ToolTip=\u0022Shortcut: Ctrl\u002BR\u0022\u003E\n\t\u003CButton.KeyboardAccelerators\u003E\n\t\t\u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022R\u0022 /\u003E\n\t\u003C/Button.KeyboardAccelerators\u003E\n\u003C/Button\u003E\n\t\n\u003CButton Click=\u0022MakeBlueButton_Click\u0022 Content=\u0022Blue\u0022\n\tGrid.Row=\u00221\u0022 Grid.Column=\u00221\u0022\n\tToolTipService.ToolTip=\u0022Shortcut: Ctrl\u002BB\u0022\u003E\n\t\u003CButton.KeyboardAccelerators\u003E\n\t\t\u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022B\u0022 /\u003E\n\t\u003C/Button.KeyboardAccelerators\u003E\n\u003C/Button\u003E\n\n\u003C!--\n Chartreuse is an uncommon color, so we explain it in the tooltip.\n This replaces the auto-generated tooltip, so we manually mention\n the hotkey in the custom tooltip.\n--\u003E\n\u003CButton Click=\u0022MakeChartreuseButton_Click\u0022 Content=\u0022Chartreuse\u0022\n\tGrid.Row=\u00221\u0022 Grid.Column=\u00221\u0022\n\tToolTipService.ToolTip=\u0022A greenish yellow (Ctrl\u002BG)\u0022\u003E\n\t\u003CButton.KeyboardAccelerators\u003E\n\t\t\u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022G\u0022 /\u003E\n\t\u003C/Button.KeyboardAccelerators\u003E\n\u003C/Button\u003E\n\u003C/Grid\u003E",
+ "code": "private void MakeRedButton_Click(object sender, RoutedEventArgs e)\n{\n ColorRectangle.Fill = new SolidColorBrush(Colors.Red);\n}\nprivate void MakeBlueButton_Click(object sender, RoutedEventArgs e)\n{\n ColorRectangle.Fill = new SolidColorBrush(Colors.Blue);\n}\nprivate void MakeChartreuseButton_Click(object sender, RoutedEventArgs e)\n{\n ColorRectangle.Fill = new SolidColorBrush(Colors.Chartreuse);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardAccelerators.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccelerators.txt",
+ "name": "Accelerators"
+ }
+ },
+ {
+ "header": "Access Keys",
+ "xaml": "\u003CMenuBar\u003E\n \u003CMenuBarItem Title=\u0022File\u0022 AccessKey=\u0022F\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022New\u0022 AccessKey=\u0022N\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Open...\u0022 AccessKey=\u0022O\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Save\u0022 AccessKey=\u0022S\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Exit\u0022 AccessKey=\u0022E\u0022 /\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Edit\u0022 AccessKey=\u0022E\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Undo\u0022 AccessKey=\u0022U\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Cut\u0022 AccessKey=\u0022X\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022 AccessKey=\u0022C\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Paste\u0022 AccessKey=\u0022V\u0022 /\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Help\u0022 AccessKey=\u0022H\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022About\u0022 AccessKey=\u0022A\u0022 /\u003E\n \u003C/MenuBarItem\u003E\n\u003C/MenuBar\u003E",
+ "gallery": {
+ "snippet": "AccessibilityKeyboardAccessKeys.txt",
+ "source": "WinUIGallery/Samples/AccessibilityKeyboard/AccessibilityKeyboardAccessKeys.txt",
+ "name": "Access Keys"
+ }
+ }
+ ]
+ },
+ {
+ "id": "accessibilityscreenreader",
+ "name": "Screen Reader",
+ "description": "Inclusive design ensures meaningful content for assistive technologies.",
+ "curatedKeywords": [
+ "Narrator",
+ "AutomationProperties",
+ "assistive technology",
+ "accessibility"
+ ],
+ "docs": [
+ {
+ "title": "Accessibility",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessibility"
+ },
+ {
+ "title": "Accessibility overview",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessibility-overview"
+ },
+ {
+ "title": "Expose basic accessibility information",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/basic-accessibility-information"
+ },
+ {
+ "title": "Landmarks and Headings",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/landmarks-and-headings"
+ },
+ {
+ "title": "Accessible text requirements",
+ "uri": "https://learn.microsoft.com/windows/apps/design/accessibility/accessible-text-requirements"
+ },
+ {
+ "title": "Complete guide to Narrator",
+ "uri": "https://support.microsoft.com/windows/complete-guide-to-narrator-e4397a0d-ef4f-b386-d8ae-c172f109bdb1"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AccessibilityScreenReader",
+ "group": {
+ "id": "AccessibilityItem",
+ "title": "Accessibility"
+ },
+ "page": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPage.xaml.cs"
+ },
+ "samples": [
+ {
+ "header": "Name From Content",
+ "xaml": "\u003C!-- Most controls automatically get names from their content --\u003E\n\u003CButton Content=\u0022Download survey\u0022 /\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderNameFromContent.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromContent.txt",
+ "name": "Name From Content"
+ }
+ },
+ {
+ "header": "Name From Header",
+ "xaml": "\u003C!-- Headers are promoted to name --\u003E\n\u003CTextBox Header=\u0022Name\u0022 /\u003E\n\n\u003C!-- As are placeholders --\u003E\n\u003CTextBox PlaceholderText=\u0022Nickname\u0022 /\u003E\n\n\u003C!-- If both are provided, headers are name and placeholders are moved to description --\u003E\n\u003CTextBox Header=\u0022Email\u0022 PlaceholderText=\u0022test@example.com\u0022 MinWidth=\u0022200\u0022 /\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderNameFromHeader.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameFromHeader.txt",
+ "name": "Name From Header"
+ }
+ },
+ {
+ "header": "Name On List View",
+ "xaml": "\u003C!-- Add a name to this ListView to be heard when screen reader users enter it --\u003E\n\u003CListView Width=\u0022300\u0022\nAutomationProperties.Name=\u0022Contacts\u0022\u003E\n\u003CListViewItem\u003ENathan Quinn\u003C/ListViewItem\u003E\n\u003CListViewItem\u003EJessica Lamber\u003C/ListViewItem\u003E\n\u003CListViewItem\u003ECarl Bond\u003C/ListViewItem\u003E\n\u003CListViewItem\u003EJessica Russel\u003C/ListViewItem\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderNameOnListView.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnListView.txt",
+ "name": "Name On List View"
+ }
+ },
+ {
+ "header": "Name On Image",
+ "xaml": "\u003C!-- Add \u0022alt text\u0022 to this image so screen reader users can understand it --\u003E\n\u003CImage AutomationProperties.Name=\u0022Grapes\u0022 Source=\u0022ms-appx:///Assets/SampleMedia/grapes.jpg\u0022/\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderNameOnImage.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderNameOnImage.txt",
+ "name": "Name On Image"
+ }
+ },
+ {
+ "header": "Labeled By",
+ "xaml": "\u003CTextBlock x:Name=\u0022InputLabel\u0022 AutomationProperties.AccessibilityView=\u0022Raw\u0022 Text=\u0022Searching Photos:\u0022/\u003E\n\u003CTextBox AutomationProperties.LabeledBy=\u0022{x:Bind InputLabel}\u0022/\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderLabeledBy.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLabeledBy.txt",
+ "name": "Labeled By"
+ }
+ },
+ {
+ "header": "Description and help text: add descriptions and help text to controls",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003C!-- Use FullDescription to connect visible descriptions to their controls --\u003E\n \u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CCheckBox Content=\u0022Clear cache on exit\u0022\n AutomationProperties.FullDescription=\u0022{x:Bind ClearCacheDescription.Text}\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022ClearCacheDescription\u0022\n Text=\u0022Deletes all cached items when closing the browser. This includes cookies, images, and browsing history.\u0022\n AutomationProperties.AccessibilityView=\u0022Raw\u0022\n Foreground=\u0022{ThemeResource TextFillColorSecondaryBrush}\u0022 /\u003E\n \u003C/StackPanel\u003E\n\n \u003C!-- Use HelpText and/or tooltips to explain nuances of controls --\u003E\n \u003CButton Content=\u0022Cancel RSS subscriptions\u0022\n ToolTipService.ToolTip=\u0022Launch the cancellation wizard\u0022\n AutomationProperties.HelpText=\u0022Launch the cancellation wizard\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderDescriptionHelpTextAdd.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderDescriptionHelpTextAdd.txt",
+ "name": "Description Help Text Add"
+ }
+ },
+ {
+ "header": "Position in set: indicate the position of an element within a set",
+ "xaml": "\u003CStackPanel\u003E\n \u003C!-- Many controls automatically indicate position in set --\u003E\n \u003CTextBlock Text=\u0022Students\u0022\n Style=\u0022{ThemeResource BodyStrongTextBlockStyle}\u0022\n x:Name=\u0022StudentsLabel\u0022\n AutomationProperties.AccessibilityView=\u0022Raw\u0022 /\u003E\n \u003CListView AutomationProperties.LabeledBy=\u0022{x:Bind StudentsLabel}\u0022\u003E\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022x:String\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind}\u0022 /\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n \u003Cx:String\u003ENathan Quinn\u003C/x:String\u003E\n \u003Cx:String\u003EJessica Lamber\u003C/x:String\u003E\n \u003Cx:String\u003ECarl Bond\u003C/x:String\u003E\n \u003Cx:String\u003EJessica Russel\u003C/x:String\u003E\n \u003C/ListView\u003E\n\n \u003C!-- Custom layouts may need to specify PositionInSet and SizeOfSet manually. --\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\n Spacing=\u00228\u0022\u003E\n \u003CButton AutomationProperties.PositionInSet=\u00221\u0022\n AutomationProperties.SizeOfSet=\u00223\u0022\n Content=\u0022View\u0022 /\u003E\n \u003CButton AutomationProperties.PositionInSet=\u00222\u0022\n AutomationProperties.SizeOfSet=\u00223\u0022\n Content=\u0022Rename\u0022 /\u003E\n \u003CButton AutomationProperties.PositionInSet=\u00223\u0022\n AutomationProperties.SizeOfSet=\u00223\u0022\n Content=\u0022Delete\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderPositionIndicatePositionElement.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderPositionIndicatePositionElement.txt",
+ "name": "Position Indicate Position Element"
+ }
+ },
+ {
+ "header": "Remove a control from the content visual tree",
+ "xaml": "\u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n\u003C!-- The image is not necessary for screen readers as it does not contain any information.\n Thus we remove it from the content visual tree with AccessibilityView=\u0022Raw\u0022 --\u003E\n\u003CImage Source=\u0022/Assets/SampleMedia/treetops.jpg\u0022 AutomationProperties.AccessibilityView=\u0022Raw\u0022 Height=\u002240\u0022 VerticalAlignment=\u0022Top\u0022/\u003E\n\u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022 MaxWidth=\u0022400\u0022 Margin=\u00228,0,0,0\u0022\u003EThis is some demo text.\n The image on the left is just for decoration and serves no informational purpose.\n To prevent Narrator or other screen readers from reading out the image, we set the accessibility view to \u0022Raw\u0022 which removes it from the content visual tree.\u003C/TextBlock\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderRemoveControlContentVisual.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderRemoveControlContentVisual.txt",
+ "name": "Remove Control Content Visual"
+ }
+ },
+ {
+ "header": "Landmarks",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022200\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022*\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022200\u0022 /\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n\n \u003C!-- The navigation pane for our app --\u003E\n \u003CStackPanel\n Grid.Column=\u00220\u0022\n Spacing=\u00228\u0022\n Padding=\u00226\u0022\n Background=\u0022{ThemeResource CardStrokeColorDefaultBrush}\u0022\n CornerRadius=\u0022{StaticResource ControlCornerRadius}\u0022\n AutomationProperties.LandmarkType=\u0022Navigation\u0022\u003E\n \u003CAutoSuggestBox\n PlaceholderText=\u0022Search\u0022\n AutomationProperties.LandmarkType=\u0022Search\u0022/\u003E\n \u003CButton Content=\u0022Open settings\u0022 /\u003E\n \u003C/StackPanel\u003E\n\n \u003C!-- The main content of our app --\u003E\n \u003CStackPanel\n Grid.Column=\u00221\u0022\n Padding=\u00226\u0022\n AutomationProperties.LandmarkType=\u0022Main\u0022\u003E\n \u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022\u003E\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum\n \u003C/TextBlock\u003E\n \u003C/StackPanel\u003E\n\n \u003C!-- A custom sidebar with a custom landmark name --\u003E\n \u003CStackPanel\n Grid.Column=\u00222\u0022\n Padding=\u00226\u0022\n Background=\u0022{ThemeResource CardStrokeColorDefaultBrush}\u0022\n CornerRadius=\u0022{StaticResource ControlCornerRadius}\u0022\n Spacing=\u00228\u0022\n AutomationProperties.LandmarkType=\u0022Custom\u0022\n AutomationProperties.LocalizedLandmarkType=\u0022Current viewers\u0022\u003E\n \u003CTextBlock\n Text=\u0022Current viewers\u0022\n Style=\u0022{ThemeResource BodyStrongTextBlockStyle}\u0022\n AutomationProperties.HeadingLevel=\u0022Level1\u0022 /\u003E\n \u003CTextBlock\n Text=\u0022(No other users viewing)\u0022\n Style=\u0022{ThemeResource BodyTextBlockStyle}\u0022\n FontStyle=\u0022Italic\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderLandmarks.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderLandmarks.txt",
+ "name": "Landmarks"
+ }
+ },
+ {
+ "header": "Headings",
+ "xaml": "\u003CStackPanel MaxWidth=\u0022500\u0022\u003E\n\u003C!-- Here is the main header for the whole text. It gets HeadingLevel 1 --\u003E\n\u003CTextBlock AutomationProperties.HeadingLevel=\u0022Level1\u0022 FontSize=\u002226\u0022\u003ELorem ipsums\u003C/TextBlock\u003E\n\u003C!-- The following TextBlock is the header for the standard lorem ipsum text, thus it is only HeadingLevel 2--\u003E\n\u003CTextBlock AutomationProperties.HeadingLevel=\u0022Level2\u0022 FontSize=\u002222\u0022\u003ELorem ipsum\u003C/TextBlock\u003E\n\u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022\u003ELorem ipsum dolor sit amet, consectetur adipiscing elit. \n Pellentesque feugiat velit pulvinar, vehicula nisi at, molestie risus. \n Duis consequat auctor libero vitae consectetur. Nullam efficitur euismod lacinia.\u003C/TextBlock\u003E\n \n\u003CTextBlock AutomationProperties.HeadingLevel=\u0022Level2\u0022 FontSize=\u002222\u0022\u003ECat ipsum\u003C/TextBlock\u003E\n\u003C!-- This is the header for the standard cat ipsum section, which is hierarchically below the cat ipsum header, resulting in HeadingLevel 3 --\u003E\n\u003CTextBlock AutomationProperties.HeadingLevel=\u00223\u0022 FontSize=\u002218\u0022\u003EStandard\u003C/TextBlock\u003E\n\u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022\u003EMice litter kitter kitty litty little kitten big roar roar feed me \n but i will ruin the couch with my claws and hunt by meowing loudly at 5am next to human.\u003C/TextBlock\u003E\n\u003CTextBlock AutomationProperties.HeadingLevel=\u00223\u0022 FontSize=\u002218\u0022\u003ECat breeds\u003C/TextBlock\u003E\n\u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022\u003ETabby abyssinian for jaguar. Thai russian blue and ragdoll, ocicat. \n Mouser puma so american bobtail for donskoy balinese . Scottish fold manx so siamese.\u003C/TextBlock\u003E\n \n\u003CTextBlock AutomationProperties.HeadingLevel=\u00222\u0022 FontSize=\u002222\u0022\u003EBacon ipsum\u003C/TextBlock\u003E\n\u003CTextBlock TextWrapping=\u0022WrapWholeWords\u0022\u003EBacon ipsum dolor amet meatball nulla labore, \n tempor sirloin chicken frankfurter tail drumstick ex cupim ground round.\u003C/TextBlock\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderHeadings.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderHeadings.txt",
+ "name": "Headings"
+ }
+ },
+ {
+ "header": "Control Groups",
+ "xaml": "\u003CStackPanel AutomationProperties.Name=\u0022Album browser\u0022\u003E\n \u003CStackPanel AutomationProperties.Name=\u0022My albums\u0022\u003E\n \u003C!-- These TextBlocks could reasonably be headings, too. --\u003E\n \u003CTextBlock\n Text=\u0022My albums\u0022\n Style=\u0022{ThemeResource BodyStrongTextBlockStyle}\u0022 /\u003E\n \u003CListView\u003E\n \u003Cx:String\u003ETrip to Redmond\u003C/x:String\u003E\n \u003Cx:String\u003EVisiting Ben\u003C/x:String\u003E\n \u003C/ListView\u003E\n \u003C/StackPanel\u003E\n \u003CStackPanel AutomationProperties.Name=\u0022Shared with me\u0022\u003E\n \u003CTextBlock\n Text=\u0022Shared with me\u0022\n Style=\u0022{ThemeResource BodyStrongTextBlockStyle}\u0022 /\u003E\n \u003CListView\u003E\n \u003Cx:String\u003EPaul\u0027s winter vacation\u003C/x:String\u003E\n \u003Cx:String\u003ECool street photography\u003C/x:String\u003E\n \u003Cx:String\u003EValeria\u0027s cat\u003C/x:String\u003E\n \u003C/ListView\u003E\n \u003C/StackPanel\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "AccessibilityScreenReaderControlGroups.txt",
+ "source": "WinUIGallery/Samples/AccessibilityScreenReader/AccessibilityScreenReaderControlGroups.txt",
+ "name": "Control Groups"
+ }
+ }
+ ]
+ },
+ {
+ "id": "acrylic",
+ "name": "AcrylicBrush",
+ "description": "A translucent material recommended for panel backgrounds.",
+ "details": "A translucent material recommended for panel backgrounds.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media",
+ "relatedControls": [
+ "System Backdrops (Mica/Acrylic)",
+ "RadialGradientBrush",
+ "ThemeShadow"
+ ],
+ "curatedKeywords": [
+ "acrylic",
+ "material",
+ "translucent",
+ "blur",
+ "AcrylicBrush"
+ ],
+ "docs": [
+ {
+ "title": "AcrylicBrush - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.acrylicbrush"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/acrylic"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Acrylic",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/Acrylic/AcrylicPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Acrylic/AcrylicPage.xaml.cs",
+ "badges": [
+ "Updated"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#RadialGradientBrush",
+ "microsoft/WinUI-Gallery#SystemBackdrops",
+ "microsoft/WinUI-Gallery#ThemeShadow"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Default in-app acrylic brush.",
+ "xaml": "\u003CRectangle Fill=\u0022{ThemeResource AcrylicInAppFillColorDefaultBrush}\u0022 /\u003E",
+ "gallery": {
+ "snippet": "DefaultAppAcrylicBrush.txt",
+ "source": "WinUIGallery/Samples/Acrylic/DefaultAppAcrylicBrush.txt",
+ "name": "Default App Acrylic Brush"
+ }
+ },
+ {
+ "header": "Custom acrylic in-app brush.",
+ "xaml": "\u003CRectangle Fill=\u0022{ThemeResource CustomAcrylicInAppBrush}\u0022 /\u003E\n\n\u003CResourceDictionary x:Key=\u0022Default\u0022\u003E\n \u003Cmedia:AcrylicBrush x:Key=\u0022CustomAcrylicBrush\u0022 /\u003E\n\u003C/ResourceDictionary\u003E",
+ "xmlnsImports": [
+ "xmlns:media=\u0022using:Microsoft.UI.Xaml.Media\u0022"
+ ],
+ "gallery": {
+ "snippet": "CustomAcrylicAppBrush.txt",
+ "source": "WinUIGallery/Samples/Acrylic/CustomAcrylicAppBrush.txt",
+ "name": "Custom Acrylic App Brush",
+ "xamlPlaceholdersDropped": [
+ "OpacitySlider",
+ "TintColor",
+ "FallbackColor"
+ ]
+ }
+ },
+ {
+ "header": "Luminosity with in-app Acrylic.",
+ "xaml": "\u003CRectangle Fill=\u0022{ThemeResource CustomAcrylicInAppLuminosity}\u0022 /\u003E\n\n\u003CResourceDictionary x:Key=\u0022Default\u0022\u003E\n \u003Cmedia:AcrylicBrush x:Key=\u0022CustomAcrylicInAppLuminosity\u0022 TintColor=\u0022SkyBlue\u0022 FallbackColor=\u0022SkyBlue\u0022 /\u003E\n\u003C/ResourceDictionary\u003E",
+ "xmlnsImports": [
+ "xmlns:media=\u0022using:Microsoft.UI.Xaml.Media\u0022"
+ ],
+ "gallery": {
+ "snippet": "LuminosityAppAcrylic.txt",
+ "source": "WinUIGallery/Samples/Acrylic/LuminosityAppAcrylic.txt",
+ "name": "Luminosity App Acrylic",
+ "xamlPlaceholdersDropped": [
+ "OpacitySlider",
+ "TintLuminositySlider"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "animatedicon",
+ "name": "AnimatedIcon",
+ "description": "An element that displays and controls an icon that animates when the user interacts with the control.",
+ "details": "An element that displays and controls an icon that animates when the user interacts with the control.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AnimatedVisualPlayer",
+ "IconElement"
+ ],
+ "xmlnsImports": [
+ "xmlns:animatedvisuals=\u0022using:Microsoft.UI.Xaml.Controls.AnimatedVisuals\u0022"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.AnimatedVisuals",
+ "Microsoft.UI.Xaml.Input",
+ "System"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "IconElement"
+ ],
+ "curatedKeywords": [
+ "animated icon",
+ "icon animation",
+ "Lottie icon"
+ ],
+ "docs": [
+ {
+ "title": "AnimatedIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.animatedicon"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/animated-icon"
+ },
+ {
+ "title": "Lottie Overview",
+ "uri": "https://learn.microsoft.com/windows/communitytoolkit/animations/lottie"
+ },
+ {
+ "title": "Lottie Windows - GitHub",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.animatedvisualplayer"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AnimatedIcon",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/AnimatedIcon/AnimatedIconPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AnimatedIcon/AnimatedIconPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "IconElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AnimatedVisualPlayer",
+ "microsoft/WinUI-Gallery#IconElement"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Adding AnimatedIcon to a button",
+ "xaml": "\u003CButton PointerEntered=\u0022Button_PointerEntered\u0022 PointerExited=\u0022Button_PointerExited\u0022 Width=\u002275\u0022\u003E\n \u003CAnimatedIcon x:Name=\u0022SearchAnimatedIcon\u0022\u003E\n \u003CAnimatedIcon.Source\u003E\n \u003Canimatedvisuals:AnimatedFindVisualSource/\u003E\n \u003C/AnimatedIcon.Source\u003E\n \u003CAnimatedIcon.FallbackIconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Find\u0022/\u003E\n \u003C/AnimatedIcon.FallbackIconSource\u003E\n \u003C/AnimatedIcon\u003E\n\u003C/Button\u003E",
+ "code": "private void Button_PointerEntered(object sender, PointerRoutedEventArgs e)\n{\n AnimatedIcon.SetState(this.SearchAnimatedIcon, \u0022PointerOver\u0022);\n}\n\nprivate void Button_PointerExited(object sender, PointerRoutedEventArgs e)\n{\n AnimatedIcon.SetState(this.SearchAnimatedIcon, \u0022Normal\u0022);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AddingAnimatediconButton.txt",
+ "source": "WinUIGallery/Samples/AnimatedIcon/AddingAnimatediconButton.txt",
+ "name": "Adding Animatedicon Button"
+ }
+ },
+ {
+ "header": "Adding AnimatedIcon to a NavigationView",
+ "xaml": "\u003CNavigationView\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content = \u0022Game Settings\u0022\u003E\n \u003CNavigationViewItem.Icon\u003E\n \u003CAnimatedIcon x:Name=\u0027AnimatedIcon\u0027\u003E\n \u003CAnimatedIcon.Source\u003E\n \u003Canimatedvisuals:AnimatedSettingsVisualSource/\u003E\n \u003C/AnimatedIcon.Source\u003E\n \u003CAnimatedIcon.FallbackIconSource\u003E\n \u003CFontIconSource Glyph=\u0022\u0026#xE713;\u0022/\u003E\n \u003C/AnimatedIcon.FallbackIconSource\u003E\n \u003C/AnimatedIcon\u003E\n \u003C/NavigationViewItem.Icon\u003E\n \u003C/NavigationViewItem\u003E\n \u003C/NavigationView.MenuItems\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "AddingAnimatediconNavigationview.txt",
+ "source": "WinUIGallery/Samples/AnimatedIcon/AddingAnimatediconNavigationview.txt",
+ "name": "Adding Animatedicon Navigationview"
+ }
+ }
+ ]
+ },
+ {
+ "id": "animatedvisualplayer",
+ "name": "AnimatedVisualPlayer",
+ "description": "An element to render and control playback of motion graphics.",
+ "details": "An element to render and control playback of motion graphics.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AnimatedIcon"
+ ],
+ "xmlnsImports": [
+ "xmlns:animatedvisuals=\u0022using:AnimatedVisuals\u0022"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "Lottie",
+ "animation",
+ "motion graphics"
+ ],
+ "docs": [
+ {
+ "title": "AnimatedVisualPlayer - API",
+ "uri": "https://learn.microsoft.com/windows/winui/api/microsoft.ui.xaml.controls.animatedvisualplayer"
+ },
+ {
+ "title": "Full Samples",
+ "uri": "ms-windows-store://pdp/?productid=9N3J5TG8FF7F"
+ },
+ {
+ "title": "Tutorials",
+ "uri": "https://learn.microsoft.com/windows/communitytoolkit/animations/lottie#tutorials"
+ },
+ {
+ "title": "Lottie Overview",
+ "uri": "https://learn.microsoft.com/windows/communitytoolkit/animations/lottie"
+ },
+ {
+ "title": "Lottie Windows - GitHub",
+ "uri": "https://github.com/CommunityToolkit/Lottie-Windows"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AnimatedVisualPlayer",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/AnimatedVisualPlayer/AnimatedVisualPlayerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AnimatedVisualPlayer/AnimatedVisualPlayerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AnimatedIcon"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Playback of a Lottie animation.",
+ "xaml": "\u003CAnimatedVisualPlayer x:Name=\u0022Player\u0022 AutoPlay=\u0022False\u0022\u003E\n \u003Canimatedvisuals:LottieLogo1/\u003E\n\u003C/AnimatedVisualPlayer\u003E",
+ "gallery": {
+ "snippet": "AnimatedVisualPlayerPlaybackLottieAnimation.txt",
+ "source": "WinUIGallery/Samples/AnimatedVisualPlayer/AnimatedVisualPlayerPlaybackLottieAnimation.txt",
+ "name": "Playback Lottie Animation"
+ }
+ }
+ ]
+ },
+ {
+ "id": "annotatedscrollbar",
+ "name": "AnnotatedScrollBar",
+ "description": "A control that extends a regular vertical scrollbar\u0027s functionality for an easy navigation through large collections.",
+ "details": "The AnnotatedScrollBar lets you navigate through a large collection of items via a clickable rail with labels which act as markers.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ItemsView",
+ "ScrollView"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives",
+ "Microsoft.UI.Xaml.Media",
+ "System",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "annotated scroll",
+ "navigation"
+ ],
+ "docs": [
+ {
+ "title": "AnnotatedScrollBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.annotatedscrollbar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AnnotatedScrollBar",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/AnnotatedScrollBar/AnnotatedScrollBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AnnotatedScrollBar/AnnotatedScrollBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ItemsView",
+ "microsoft/WinUI-Gallery#ScrollView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "AnnotatedScrollBar linked to a ScrollView.",
+ "xaml": "\u003CScrollView x:Name=\u0022scrollView\u0022\n Background=\u0022LightGray\u0022 MaxWidth=\u0022800\u0022 MaxHeight=\u0022500\u0022\n VerticalScrollBarVisibility=\u0022Hidden\u0022\u003E\n \u003C!-- ... --\u003E\n\u003C/ScrollView\u003E\n \n\u003CAnnotatedScrollBar x:Name=\u0022annotatedScrollBar\u0022\n Margin=\u00224,0,48,0\u0022 MaxHeight=\u0022500\u0022\n HorizontalAlignment=\u0022Right\u0022\n DetailLabelRequested=\u0022AnnotatedScrollBar_DetailLabelRequested\u0022/\u003E",
+ "code": "private void AnnotatedScrollBarPage_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)\n{\n scrollView.ScrollPresenter.VerticalScrollController = annotatedScrollBar.ScrollController;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AnnotatedscrollbarLinkedScrollview.txt",
+ "source": "WinUIGallery/Samples/AnnotatedScrollBar/AnnotatedscrollbarLinkedScrollview.txt",
+ "name": "Linked Scrollview"
+ }
+ }
+ ]
+ },
+ {
+ "id": "appbarbutton",
+ "name": "AppBarButton",
+ "description": "A button that\u0027s styled for use in a CommandBar.",
+ "details": "AppBarButton differs from standard buttons in several ways:\n- Their default appearance is a transparent background with a smaller size.\n- You use the Label and Icon properties to set the content instead of the Content property. The Content property is ignored.\n- The button\u0027s IsCompact property controls its size.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AppBarToggleButton",
+ "AppBarSeparator",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "Button"
+ ],
+ "curatedKeywords": [
+ "toolbar button",
+ "command button"
+ ],
+ "docs": [
+ {
+ "title": "AppBarButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.appbarbutton"
+ },
+ {
+ "title": "SymbolIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.symbolicon"
+ },
+ {
+ "title": "FontIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.fonticon"
+ },
+ {
+ "title": "BitmapIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.bitmapicon"
+ },
+ {
+ "title": "PathIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.pathicon"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/command-bar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppBarButton",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/AppBarButton/AppBarButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppBarButton/AppBarButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "Button"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarSeparator",
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#CommandBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An AppBarButton with a symbol icon.",
+ "xaml": "\u003CAppBarButton Icon=\u0022Like\u0022 Label=\u0022SymbolIcon\u0022 Click=\u0022AppBarButton_Click\u0022/\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonSymbolIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonSymbolIcon.txt",
+ "name": "Symbol Icon"
+ }
+ },
+ {
+ "header": "An AppBarButton with a bitmap icon.",
+ "xaml": "\u003CAppBarButton Label=\u0022BitmapIcon\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarButton.Icon\u003E\n \u003CBitmapIcon UriSource=\u0022ms-appx:///Assets/SampleMedia/Slices2.png\u0022/\u003E\n \u003C/AppBarButton.Icon\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonBitmapIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonBitmapIcon.txt",
+ "name": "Bitmap Icon"
+ }
+ },
+ {
+ "header": "An AppBarButton with a font icon.",
+ "xaml": "\u003CAppBarButton Label=\u0022FontIcon\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarButton.Icon\u003E\n \u003CFontIcon FontFamily=\u0022Candara\u0022 Glyph=\u0022\u0026#x03A3;\u0022/\u003E\n \u003C/AppBarButton.Icon\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonFontIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonFontIcon.txt",
+ "name": "Font Icon"
+ }
+ },
+ {
+ "header": "An AppBarButton with a path icon.",
+ "xaml": "\u003CAppBarButton Label=\u0022PathIcon\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarButton.Content\u003E\n \u003CViewbox Stretch=\u0022Uniform\u0022\u003E\n \u003CPathIcon Data=\u0022F1 M 20,20L 24,10L 24,24L 5,24\u0022/\u003E\n \u003C/Viewbox\u003E\n \u003C/AppBarButton.Content\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonPathIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonPathIcon.txt",
+ "name": "Path Icon"
+ }
+ },
+ {
+ "header": "An AppBarButton with a KeyboardAccelerator",
+ "xaml": "\u003CAppBarButton Icon=\u0022Save\u0022 Label=\u0022Save\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarButton.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022S\u0022/\u003E\n \u003C/AppBarButton.KeyboardAccelerators\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonKeyboardaccelerator.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonKeyboardaccelerator.txt",
+ "name": "Keyboardaccelerator"
+ }
+ },
+ {
+ "header": "An AppBarButton that opens a Flyout containing an input control.",
+ "xaml": "\u003CAppBarButton\n AllowFocusOnInteraction=\u0022True\u0022\n Icon=\u0022Edit\u0022\n Label=\u0022Edit\u0022\u003E\n \u003CAppBarButton.Flyout\u003E\n \u003CFlyout\u003E\n \u003CTextBox MinWidth=\u0022240\u0022 PlaceholderText=\u0022Input text here\u0022 /\u003E\n \u003C/Flyout\u003E\n \u003C/AppBarButton.Flyout\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonOpensFlyoutContaining.txt",
+ "source": "WinUIGallery/Samples/AppBarButton/AppbarbuttonOpensFlyoutContaining.txt",
+ "name": "Opens Flyout Containing"
+ }
+ }
+ ]
+ },
+ {
+ "id": "appbarseparator",
+ "name": "AppBarSeparator",
+ "description": "A vertical line that\u0027s used to visually separate groups of commands in an app bar.",
+ "details": "An AppBarSeparator creates a vertical line to visually separate groups of commands in a app bar. It has a compact state with reduced padding to match the compact state of the AppBarButton and AppBarToggleButton controls.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AppBarButton",
+ "AppBarToggleButton",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "divider"
+ ],
+ "docs": [
+ {
+ "title": "AppBarSeparator - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.appbarseparator"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/command-bar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppBarSeparator",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/AppBarSeparator/AppBarSeparatorPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppBarSeparator/AppBarSeparatorPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#CommandBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "AppBarButtons separated by AppBarSeparators.",
+ "xaml": "\u003CCommandBar\u003E\n \u003CCommandBar.PrimaryCommands\u003E\n \u003CAppBarButton Icon=\u0022AttachCamera\u0022 Label=\u0022Attach Camera\u0022/\u003E\n \u003CAppBarSeparator /\u003E\n \u003CAppBarButton Icon=\u0022Like\u0022 Label=\u0022Like\u0022/\u003E\n \u003CAppBarButton Icon=\u0022Dislike\u0022 Label=\u0022Dislike\u0022/\u003E\n \u003CAppBarSeparator /\u003E\n \u003CAppBarButton Icon=\u0022Orientation\u0022 Label=\u0022Orientation\u0022/\u003E\n \u003C/CommandBar.PrimaryCommands\u003E\n\u003C/CommandBar\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonsSeparatedAppbarseparators.txt",
+ "source": "WinUIGallery/Samples/AppBarSeparator/AppbarbuttonsSeparatedAppbarseparators.txt",
+ "name": "Appbarbuttons Separated Appbarseparators"
+ }
+ }
+ ]
+ },
+ {
+ "id": "appbartogglebutton",
+ "name": "AppBarToggleButton",
+ "description": "A button that can be on, off, or indeterminate like a CheckBox, and is styled for use in an app bar or other specialized UI.",
+ "details": "An AppBarToggleButton looks like an AppBarButton, but works like a CheckBox. It typically has two states, checked (on) or unchecked (off), but can be indeterminate if the IsThreeState property is true. You can determine it\u0027s state by checking the IsChecked property.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AppBarButton",
+ "AppBarSeparator",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "curatedKeywords": [
+ "toolbar toggle",
+ "command toggle"
+ ],
+ "docs": [
+ {
+ "title": "AppBarToggleButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.appbartogglebutton"
+ },
+ {
+ "title": "SymbolIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.symbolicon"
+ },
+ {
+ "title": "FontIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.fonticon"
+ },
+ {
+ "title": "BitmapIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.bitmapicon"
+ },
+ {
+ "title": "PathIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.pathicon"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/command-bar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppBarToggleButton",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/AppBarToggleButton/AppBarToggleButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppBarToggleButton/AppBarToggleButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#AppBarSeparator",
+ "microsoft/WinUI-Gallery#CommandBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An AppBarToggleButton with a symbol icon.",
+ "xaml": "\u003CAppBarToggleButton Icon=\u0022Shuffle\u0022 Label=\u0022SymbolIcon\u0022 Click=\u0022AppBarButton_Click\u0022/\u003E",
+ "gallery": {
+ "snippet": "AppbartogglebuttonSymbolIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarToggleButton/AppbartogglebuttonSymbolIcon.txt",
+ "name": "Symbol Icon"
+ }
+ },
+ {
+ "header": "An AppBarToggleButton with a bitmap icon.",
+ "xaml": "\u003CAppBarToggleButton Label=\u0022BitmapIcon\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarToggleButton.Icon\u003E\n \u003CBitmapIcon UriSource=\u0022ms-appx:///Assets/SampleMedia/Slices2.png\u0022/\u003E\n \u003C/AppBarToggleButton.Icon\u003E\n\u003C/AppBarToggleButton\u003E",
+ "gallery": {
+ "snippet": "AppbartogglebuttonBitmapIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarToggleButton/AppbartogglebuttonBitmapIcon.txt",
+ "name": "Bitmap Icon"
+ }
+ },
+ {
+ "header": "An AppBarToggleButton with a font icon.",
+ "xaml": "\u003CAppBarToggleButton Label=\u0022FontIcon\u0022 Click=\u0022AppBarButton_Click\u0022\u003E\n \u003CAppBarToggleButton.Icon\u003E\n \u003CFontIcon FontFamily=\u0022Candara\u0022 Glyph=\u0022\u0026#x03A3;\u0022/\u003E\n \u003C/AppBarToggleButton.Icon\u003E\n\u003C/AppBarToggleButton\u003E",
+ "gallery": {
+ "snippet": "AppbartogglebuttonFontIcon.txt",
+ "source": "WinUIGallery/Samples/AppBarToggleButton/AppbartogglebuttonFontIcon.txt",
+ "name": "Font Icon"
+ }
+ },
+ {
+ "header": "A three-state AppBarToggleButton with a path icon.",
+ "xaml": "\u003CAppBarToggleButton Label=\u0022PathIcon\u0022 Click=\u0022AppBarButton_Click\u0022 IsThreeState=\u0022True\u0022\u003E\n \u003CAppBarToggleButton.Icon\u003E\n \u003CPathIcon Data=\u0022F1 M 20,20L 24,10L 24,24L 5,24\u0022/\u003E\n \u003C/AppBarToggleButton.Icon\u003E\n\u003C/AppBarToggleButton\u003E",
+ "gallery": {
+ "snippet": "ThreeStateAppbartogglebuttonPath.txt",
+ "source": "WinUIGallery/Samples/AppBarToggleButton/ThreeStateAppbartogglebuttonPath.txt",
+ "name": "Three State Appbartogglebutton Path"
+ }
+ }
+ ]
+ },
+ {
+ "id": "appnotification",
+ "name": "App notifications",
+ "description": "Send notifications that appear in the Action Center and as toast popups.",
+ "details": "Send rich, interactive notifications from your app. Notifications can include text, images, and actions.",
+ "apiNamespace": "Microsoft.Windows.Notifications",
+ "relatedControls": [
+ "Badge notifications"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.Windows.AppNotifications",
+ "Microsoft.Windows.AppNotifications.Builder",
+ "System",
+ "System.Collections.Generic"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "toast",
+ "notification",
+ "Action Center",
+ "toast notification"
+ ],
+ "docs": [
+ {
+ "title": "AppNotification - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.appnotifications.appnotification"
+ },
+ {
+ "title": "AppNotificationManager - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.appnotifications.appnotificationmanager"
+ },
+ {
+ "title": "AppNotificationBuilder - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.appnotifications.builder.appnotificationbuilder"
+ },
+ {
+ "title": "Toast notifications",
+ "uri": "https://learn.microsoft.com/windows/apps/design/shell/tiles-and-notifications/toast-notifications-overview"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppNotification",
+ "group": {
+ "id": "Shell",
+ "title": "Shell"
+ },
+ "page": "WinUIGallery/Samples/AppNotification/AppNotificationPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppNotification/AppNotificationPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#BadgeNotificationManager"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic notification",
+ "code": "AppNotification notification = new AppNotificationBuilder()\n .AddText(\u0022Welcome to WinUI 3 Gallery\u0022)\n .AddText(\u0022Explore interactive samples and discover the power of modern Windows UI.\u0022)\n .BuildNotification();\n\nAppNotificationManager.Default.Show(notification);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppNotificationBasicNotification.txt",
+ "source": "WinUIGallery/Samples/AppNotification/AppNotificationBasicNotification.txt",
+ "name": "Basic Notification"
+ }
+ },
+ {
+ "header": "Informational notification with logo and custom audio",
+ "code": "AppNotification notification = new AppNotificationBuilder()\n .AddText(\u0022Control Highlight: PersonPicture\u0022)\n .AddText(\u0022Use the PersonPicture control to display user avatars with initials or images.\u0022)\n .SetAppLogoOverride(new Uri(\u0022ms-appx:///Assets/ControlImages/PersonPicture.png\u0022), AppNotificationImageCrop.Circle)\n .SetAudioEvent(AppNotificationSoundEvent.$(SelectedAppNotificationSoundEvent))\n .SetTimeStamp(DateTime.Now) \n .BuildNotification();\n\nAppNotificationManager.Default.Show(notification);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppNotificationInformationalNotificationLogoCustom.txt",
+ "source": "WinUIGallery/Samples/AppNotification/AppNotificationInformationalNotificationLogoCustom.txt",
+ "name": "Informational Notification Logo Custom",
+ "codePlaceholdersPresent": [
+ "SelectedAppNotificationSoundEvent"
+ ]
+ }
+ },
+ {
+ "header": "Visual notification with hero image and attribution",
+ "code": "AppNotification notification = new AppNotificationBuilder()\n .AddText(\u0022Harbor Scene with Boats\u0022)\n .AddText(\u0022A quiet harbor with boats gently anchored in view.\u0022)\n .SetHeroImage(new Uri(\u0022ms-appx:///Assets/SampleMedia/LandscapeImage5.jpg\u0022))\n .SetAttributionText(\u0022WinUI gallery assets\u0022)\n .BuildNotification();\n\nAppNotificationManager.Default.Show(notification);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppNotificationVisualNotificationHeroImage.txt",
+ "source": "WinUIGallery/Samples/AppNotification/AppNotificationVisualNotificationHeroImage.txt",
+ "name": "Visual Notification Hero Image"
+ }
+ },
+ {
+ "header": "Notification with AppNotification controls",
+ "code": "AppNotification notification = new AppNotificationBuilder()\n .AddText(\u0022Survey\u0022)\n .AddText(\u0022Please select your satisfaction level and leave a comment.\u0022)\n .AddComboBox(new AppNotificationComboBox(\u0022satisfaction\u0022)\n .AddItem(\u00221\u0022, \u0022Very Bad\u0022)\n .AddItem(\u00222\u0022, \u0022Bad\u0022)\n .AddItem(\u00223\u0022, \u0022Neutral\u0022)\n .AddItem(\u00224\u0022, \u0022Good\u0022)\n .AddItem(\u00225\u0022, \u0022Excellent\u0022)\n .SetSelectedItem(\u00223\u0022))\n .AddTextBox(\u0022comment\u0022, \u0022Leave a comment here...\u0022,\u0022\u0022)\n .AddButton(new AppNotificationButton(\u0022Submit\u0022)\n .AddArgument(\u0022action\u0022, \u0022submit_survey\u0022))\n .BuildNotification();\n\nAppNotificationManager.Default.Show(notification);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "NotificationAppnotificationControls.txt",
+ "source": "WinUIGallery/Samples/AppNotification/NotificationAppnotificationControls.txt",
+ "name": "Notification Appnotification Controls"
+ }
+ },
+ {
+ "header": "Notification with ProgressBar",
+ "code": "AppNotification notification = new AppNotificationBuilder()\n .AddText(\u0022Progress Bar Example\u0022)\n .AddText(\u0022This is a sample notification showing how to use a progress bar.\u0022)\n .AddProgressBar(new AppNotificationProgressBar()\n {\n Title = \u0022Demo Progress\u0022,\n Value = 0.6, // 60%\n ValueStringOverride = \u002260%\u0022,\n Status = \u0022In progress...\u0022\n })\n .BuildNotification();\n\nAppNotificationManager.Default.Show(notification);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppNotificationNotificationProgressbar.txt",
+ "source": "WinUIGallery/Samples/AppNotification/AppNotificationNotificationProgressbar.txt",
+ "name": "Notification Progressbar"
+ }
+ }
+ ]
+ },
+ {
+ "id": "appwindow",
+ "name": "AppWindow",
+ "description": "A flexible, customizable window management system for app development.",
+ "details": "AppWindow provides advanced window management, allowing customization of size, position, and presentation. This sample showcases different ways to create, display, and control windows for enhanced flexibility.",
+ "apiNamespace": "Microsoft.UI.Windowing",
+ "relatedControls": [
+ "AppWindowTitleBar",
+ "TitleBar",
+ "Window"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "window management",
+ "windowing"
+ ],
+ "docs": [
+ {
+ "title": "AppWindow - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindow"
+ },
+ {
+ "title": "Window - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window"
+ },
+ {
+ "title": "AppWindowPresenter - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindowpresenter"
+ },
+ {
+ "title": "OverlappedPresenter - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.overlappedpresenter"
+ },
+ {
+ "title": "FullScreenPresenter - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.fullscreenpresenter"
+ },
+ {
+ "title": "CompactOverlayPresenter - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.compactoverlaypresenter"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppWindow",
+ "group": {
+ "id": "MultipleWindows",
+ "title": "Windowing"
+ },
+ "page": "WinUIGallery/Samples/AppWindow/AppWindowPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppWindow/AppWindowPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppWindowTitleBar",
+ "microsoft/WinUI-Gallery#TitleBar",
+ "microsoft/WinUI-Gallery#Windowing"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Creating and customizing an AppWindow from a Window instance",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\n\nnamespace YourNamespace;\n \npublic sealed partial class SampleWindow1 : Window\n{ \n public SampleWindow1()\n {\n this.InitializeComponent();\n\n // Set the window title\n AppWindow.Title = \u0022This is a title\u0022;\n\n // Set the window size (including borders)\n AppWindow.Resize(new Windows.Graphics.SizeInt32(800, 500));\n\n // Set the window position on screen\n AppWindow.Move(new Windows.Graphics.PointInt32(50, 50));\n \n // Set the taskbar icon (displayed in the taskbar)\n AppWindow.SetTaskbarIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n\n // Set the title bar icon (displayed in the window\u0027s title bar)\n AppWindow.SetTitleBarIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n\n // Set the window icon (affects both taskbar and title bar, can be omitted if the above two are set)\n // AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022); \n \n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n }\n \n private void Show_Click(object sender, RoutedEventArgs e)\n {\n AppWindow.Hide();\n Task.Delay(3000).ContinueWith(t =\u003E AppWindow.Show());\n }\n\n private void Hide_Click(object sender, RoutedEventArgs e)\n {\n AppWindow.Hide();\n }\n\n private void Close_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CreatingCustomizingAppwindowWindow.txt",
+ "source": "WinUIGallery/Samples/AppWindow/CreatingCustomizingAppwindowWindow.txt",
+ "name": "Creating Customizing Appwindow Window",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "Centering AppWindow on the screen using the available display area",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\nusing Windows.Graphics;\n\nnamespace YourNamesapace;\n\npublic sealed partial class SampleWindow2 : Window\n{\n public SampleWindow2()\n {\n this.InitializeComponent();\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n\n // Center the window on the screen.\n CenterWindow();\n }\n\n // Centers the given AppWindow on the screen based on the available display area.\n private void CenterWindow()\n {\n var area = DisplayArea.GetFromWindowId(AppWindow.Id, DisplayAreaFallback.Nearest)?.WorkArea;\n if (area == null) return;\n AppWindow.Move(new PointInt32((area.Value.Width - AppWindow.Size.Width) / 2, (area.Value.Height - AppWindow.Size.Height) / 2));\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CenteringAppwindowScreenAvailable.txt",
+ "source": "WinUIGallery/Samples/AppWindow/CenteringAppwindowScreenAvailable.txt",
+ "name": "Centering Appwindow Screen Available",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "AppWindow with OverlapedPresenter",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\nusing System.Threading.Tasks;\n\nnamespace YourNamespace;\n\npublic sealed partial class SampleWindow3 : Window\n{\n public SampleWindow3()\n {\n this.InitializeComponent();\n\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode; \n OverlappedPresenter presenter = OverlappedPresenter.Create();\n \n presenter.IsAlwaysOnTop = $(IsAlwaysOnTop);\n presenter.IsMaximizable = $(IsMaximizable);\n presenter.IsMinimizable = $(IsMinimizable);\n presenter.IsResizable = $(IsResizable);\n presenter.SetBorderAndTitleBar($(HasBorder), $(HasTitleBar));\n\n AppWindow.SetPresenter(presenter);\n\n SizeChanged \u002B= SampleWindow3_SizeChanged;\n }\n\n private void MaximizeRestoreBtn_Click(object sender, RoutedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n if (presenter.State == OverlappedPresenterState.Maximized)\n {\n presenter.Restore();\n }\n else\n {\n presenter.Maximize();\n }\n }\n\n private void SampleWindow3_SizeChanged(object sender, WindowSizeChangedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n MaximizeRestoreBtn.Content = presenter.State == OverlappedPresenterState.Maximized ? \u0022Restore\u0022 : \u0022Maximize\u0022;\n }\n\n private void MinimizeBtn_Click(object sender, RoutedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n presenter.Minimize();\n }\n\n private void RestoreBtn_Click(object sender, RoutedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n presenter.Minimize();\n Task.Delay(3000).ContinueWith(t =\u003E presenter.Restore());\n }\n\n private void CloseBtn_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppwindowOverlapedpresenter.txt",
+ "source": "WinUIGallery/Samples/AppWindow/AppwindowOverlapedpresenter.txt",
+ "name": "Overlapedpresenter",
+ "xamlOmittedAsMalformed": true,
+ "codePlaceholdersPresent": [
+ "IsAlwaysOnTop",
+ "IsMaximizable",
+ "IsMinimizable",
+ "IsResizable",
+ "HasBorder",
+ "HasTitleBar"
+ ]
+ }
+ },
+ {
+ "header": "Setting the minimum and maximum width / height on an AppWindow using OverlappedPresenter",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\nusing System.Threading.Tasks;\n\nnamespace WinUIGallery.Samples.SamplePages;\n\npublic sealed partial class SampleWindow4 : Window\n{\n public SampleWindow4(int MinWidth, int MinHeight, int MaxWidth, int MaxHeight)\n {\n this.InitializeComponent();\n\n AppWindow.Resize(new Windows.Graphics.SizeInt32(800, 500));\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n\n OverlappedPresenter presenter = OverlappedPresenter.Create();\n presenter.PreferredMinimumWidth = MinWidth;\n presenter.PreferredMinimumHeight = MinHeight;\n presenter.PreferredMaximumWidth = MaxWidth;\n presenter.PreferredMaximumHeight = MaxHeight;\n presenter.IsMaximizable = false;\n\n AppWindow.SetPresenter(presenter);\n }\n\n private void MinimizeBtn_Click(object sender, RoutedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n presenter.Minimize();\n }\n\n private void RestoreBtn_Click(object sender, RoutedEventArgs e)\n {\n OverlappedPresenter presenter = (OverlappedPresenter)AppWindow.Presenter;\n presenter.Minimize();\n Task.Delay(3000).ContinueWith(t =\u003E presenter.Restore());\n }\n\n private void CloseBtn_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppWindowSettingMinimumMaximumWidth.txt",
+ "source": "WinUIGallery/Samples/AppWindow/AppWindowSettingMinimumMaximumWidth.txt",
+ "name": "Setting Minimum Maximum Width",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "Modal window with OverlappedPresenter using AppWindow",
+ "code": "using Microsoft.UI;\nusing Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\nusing System;\nusing System.Runtime.InteropServices;\nusing WinRT.Interop;\n\nnamespace YourNamespace;\n\npublic sealed partial class ModalWindow : Window\n{\n public ModalWindow()\n {\n this.InitializeComponent();\n\n var dpi = Windows.Win32.PInvoke.GetDpiForWindow(new Windows.Win32.Foundation.HWND(WinRT.Interop.WindowNative.GetWindowHandle(this)));\n var scalingFactor = (float)dpi / 96;\n\n AppWindow.Resize(new Windows.Graphics.SizeInt32((int)(400.0f * scalingFactor), (int)(300.0f * scalingFactor)));\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n\n OverlappedPresenter presenter = OverlappedPresenter.CreateForDialog();\n\n // Set this modal window\u0027s owner (the main application window).\n // The main window can be retrieved from App.xaml.cs if it\u0027s set as a static property.\n SetWindowOwner(owner: App.StartupWindow);\n\n // Make the window modal (blocks interaction with the owner window until closed).\n presenter.IsModal = true;\n\n // Apply the presenter settings to the AppWindow.\n AppWindow.SetPresenter(presenter);\n\n // Show the modal window.\n AppWindow.Show();\n\n Closed \u002B= ModalWindow_Closed;\n }\n\n // Sets the owner window of the modal window.\n private void SetWindowOwner(Window owner)\n {\n // Get the HWND (window handle) of the owner window (main window).\n IntPtr ownerHwnd = WindowNative.GetWindowHandle(owner);\n\n // Get the HWND of the AppWindow (modal window).\n IntPtr ownedHwnd = Win32Interop.GetWindowFromWindowId(AppWindow.Id);\n\n // Set the owner window using SetWindowLongPtr for 64-bit systems\n // or SetWindowLong for 32-bit systems.\n if (IntPtr.Size == 8) // Check if the system is 64-bit\n {\n SetWindowLongPtr(ownedHwnd, -8, ownerHwnd); // -8 = GWLP_HWNDPARENT\n }\n else // 32-bit system\n {\n SetWindowLong(ownedHwnd, -8, ownerHwnd); // -8 = GWL_HWNDPARENT\n }\n }\n\n // Import the Windows API function SetWindowLongPtr for modifying window properties on 64-bit systems.\n [DllImport(\u0022User32.dll\u0022, CharSet = CharSet.Auto, EntryPoint = \u0022SetWindowLongPtr\u0022)]\n public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);\n\n // Import the Windows API function SetWindowLong for modifying window properties on 32-bit systems.\n [DllImport(\u0022User32.dll\u0022, CharSet = CharSet.Auto, EntryPoint = \u0022SetWindowLong\u0022)]\n public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);\n\n private void ModalWindow_Closed(object sender, WindowEventArgs args)\n {\n // Reactivate the main application window when the modal window closes.\n App.StartupWindow.Activate();\n }\n\n private void OKButton_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n\n private void CancelButton_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ModalWindowOverlappedpresenterAppwindow.txt",
+ "source": "WinUIGallery/Samples/AppWindow/ModalWindowOverlappedpresenterAppwindow.txt",
+ "name": "Modal Window Overlappedpresenter Appwindow",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "AppWindow with FullScreenPresenter",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\n\nnamespace YourNamespace;\n\npublic sealed partial class SampleWindow6 : Window\n{\n public SampleWindow6()\n {\n this.InitializeComponent();\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n\n // Set the window to Full-Screen mode\n AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);\n }\n\n private void Close_Click(object sender, RoutedEventArgs e)\n {\n this.Close();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppwindowFullscreenpresenter.txt",
+ "source": "WinUIGallery/Samples/AppWindow/AppwindowFullscreenpresenter.txt",
+ "name": "Fullscreenpresenter",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "AppWindow with CompactOverlayPresenter",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\n\nnamespace YourNamespace;\n\npublic sealed partial class SampleWindow7 : Window\n{\n public SampleWindow7(string InitialSize)\n {\n this.InitializeComponent();\n\n AppWindow.SetIcon(\u0022Assets/Tiles/GalleryIcon.ico\u0022);\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;\n\n // Creates a CompactOverlay (Picture-in-Picture) presenter\n CompactOverlayPresenter presenter = CompactOverlayPresenter.Create();\n\n // Sets the initial size of the CompactOverlay window\n presenter.InitialSize = CompactOverlaySize.Small;\n\n // Applies the CompactOverlay presenter to the window\n AppWindow.SetPresenter(presenter);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppwindowCompactoverlaypresenter.txt",
+ "source": "WinUIGallery/Samples/AppWindow/AppwindowCompactoverlaypresenter.txt",
+ "name": "Compactoverlaypresenter",
+ "xamlOmittedAsMalformed": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "appwindowtitlebar",
+ "name": "AppWindowTitleBar",
+ "description": "Provides control over the app window title bar.",
+ "details": "Represents the title bar of an AppWindow and exposes APIs for deep, fine-grained customization, including advanced appearance changes, system button styling, and precise control over active and inactive window states.",
+ "apiNamespace": "Microsoft.UI.Windowing",
+ "relatedControls": [
+ "AppWindow",
+ "TitleBar"
+ ],
+ "usings": [
+ "Microsoft.UI.Windowing",
+ "Microsoft.UI.Xaml.Controls",
+ "System",
+ "System.Collections.Generic",
+ "Windows.UI"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "title bar",
+ "caption",
+ "custom title bar"
+ ],
+ "docs": [
+ {
+ "title": "AppWindowTitleBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindowtitlebar"
+ },
+ {
+ "title": "Customize the title bar",
+ "uri": "https://learn.microsoft.com/windows/apps/develop/title-bar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AppWindowTitleBar",
+ "group": {
+ "id": "MultipleWindows",
+ "title": "Windowing"
+ },
+ "page": "WinUIGallery/Samples/AppWindowTitleBar/AppWindowTitleBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AppWindowTitleBar/AppWindowTitleBarPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppWindow",
+ "microsoft/WinUI-Gallery#TitleBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "AppWindowTitleBar color customization",
+ "code": "using Microsoft.UI;\nusing Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\nusing Windows.UI;\n\npublic sealed partial class AppWindowTitleBarWindow : Window\n{\n public AppWindowTitleBarWindow()\n {\n InitializeComponent();\n\n AppWindow.TitleBar.BackgroundColor = ColorHelper.FromArgb($(BackgroundColor));\n AppWindow.TitleBar.ForegroundColor = ColorHelper.FromArgb($(ForegroundColor));\n AppWindow.TitleBar.ButtonBackgroundColor = ColorHelper.FromArgb($(ButtonBackgroundColor));\n AppWindow.TitleBar.ButtonForegroundColor = ColorHelper.FromArgb($(ButtonForegroundColor));\n AppWindow.TitleBar.ButtonHoverBackgroundColor = ColorHelper.FromArgb($(ButtonHoverBackgroundColor));\n AppWindow.TitleBar.ButtonHoverForegroundColor = ColorHelper.FromArgb($(ButtonHoverForegroundColor));\n AppWindow.TitleBar.InactiveBackgroundColor = ColorHelper.FromArgb($(InactiveBackgroundColor));\n AppWindow.TitleBar.InactiveForegroundColor = ColorHelper.FromArgb($(InactiveForegroundColor));\n AppWindow.TitleBar.ButtonInactiveBackgroundColor = ColorHelper.FromArgb($(ButtonInactiveBackgroundColor));\n AppWindow.TitleBar.ButtonInactiveForegroundColor = ColorHelper.FromArgb($(ButtonInactiveForegroundColor));\n AppWindow.TitleBar.ButtonPressedBackgroundColor = ColorHelper.FromArgb($(ButtonPressedBackgroundColor));\n AppWindow.TitleBar.ButtonPressedForegroundColor = ColorHelper.FromArgb($(ButtonPressedForegroundColor));\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppwindowtitlebarColorCustomization.txt",
+ "source": "WinUIGallery/Samples/AppWindowTitleBar/AppwindowtitlebarColorCustomization.txt",
+ "name": "Color Customization",
+ "codePlaceholdersPresent": [
+ "BackgroundColor",
+ "ForegroundColor",
+ "ButtonBackgroundColor",
+ "ButtonForegroundColor",
+ "ButtonHoverBackgroundColor",
+ "ButtonHoverForegroundColor",
+ "InactiveBackgroundColor",
+ "InactiveForegroundColor",
+ "ButtonInactiveBackgroundColor",
+ "ButtonInactiveForegroundColor",
+ "ButtonPressedBackgroundColor",
+ "ButtonPressedForegroundColor"
+ ]
+ }
+ },
+ {
+ "header": "Extending content into the AppWindowTitleBar area",
+ "code": "using Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\n\npublic sealed partial class AppWindowTitleBarExtendWindow : Window\n{\n public AppWindowTitleBarExtendWindow()\n {\n InitializeComponent();\n AppWindow.TitleBar.ExtendsContentIntoTitleBar = $(ExtendsContentIntoTitleBar);\n if (AppWindow.TitleBar.ExtendsContentIntoTitleBar)\n {\n AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.$(TitleBarHeightOption);\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ExtendingContentAppwindowtitlebarArea.txt",
+ "source": "WinUIGallery/Samples/AppWindowTitleBar/ExtendingContentAppwindowtitlebarArea.txt",
+ "name": "Extending Content Appwindowtitlebar Area",
+ "codePlaceholdersPresent": [
+ "ExtendsContentIntoTitleBar",
+ "TitleBarHeightOption"
+ ]
+ }
+ },
+ {
+ "header": "AppWindowTitleBar preferred theme and height options",
+ "code": "using Microsoft.UI;\nusing Microsoft.UI.Windowing;\nusing Microsoft.UI.Xaml;\n \npublic sealed partial class AppWindowTitleBarThemeHeightWindow : Window\n{\n public AppWindowTitleBarThemeHeightWindow()\n {\n InitializeComponent();\n AppWindow.TitleBar.PreferredTheme = TitleBarTheme.$(PreferredTheme);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AppwindowtitlebarPreferredThemeHeight.txt",
+ "source": "WinUIGallery/Samples/AppWindowTitleBar/AppwindowtitlebarPreferredThemeHeight.txt",
+ "name": "Preferred Theme Height",
+ "codePlaceholdersPresent": [
+ "PreferredTheme"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "autosuggestbox",
+ "name": "AutoSuggestBox",
+ "description": "A control to provide suggestions as a user is typing.",
+ "details": "A text control that makes suggestions to users as they type. The app is notified when text has been changed by the user and is responsible for providing relevant suggestions for this control to display.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ComboBox",
+ "TextBox"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media.Imaging",
+ "System",
+ "System.Collections.Generic",
+ "System.Linq"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl"
+ ],
+ "curatedKeywords": [
+ "search box",
+ "autocomplete",
+ "suggestions",
+ "typeahead"
+ ],
+ "docs": [
+ {
+ "title": "AutoSuggestBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.autosuggestbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/auto-suggest-box"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "AutoSuggestBox",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/AutoSuggestBox/AutoSuggestBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/AutoSuggestBox/AutoSuggestBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ComboBox",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic autosuggest box.",
+ "xaml": "\u003CAutoSuggestBox TextChanged=\u0022AutoSuggestBox_TextChanged\u0022\n SuggestionChosen=\u0022AutoSuggestBox_SuggestionChosen\u0022\n Width=\u0022300\u0022 AutomationProperties.Name=\u0022Basic AutoSuggestBox\u0022/\u003E",
+ "code": "// List of cats\nprivate List\u003Cstring\u003E Cats = new List\u003Cstring\u003E()\n{\n \u0022Abyssinian\u0022,\n \u0022Aegean\u0022,\n \u0022American Bobtail\u0022,\n ...\n};\n\n// Handle text change and present suitable items\nprivate void AutoSuggestBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)\n{\n // Since selecting an item will also change the text,\n // only listen to changes caused by user entering text.\n if(args.Reason == AutoSuggestionBoxTextChangeReason.UserInput)\n {\n var suitableItems = new List\u003Cstring\u003E();\n var splitText = sender.Text.ToLower().Split(\u0022 \u0022);\n foreach(var cat in Cats)\n {\n var found = splitText.All((key)=\u003E\n {\n return cat.ToLower().Contains(key);\n });\n if(found)\n {\n suitableItems.Add(cat);\n }\n }\n if(suitableItems.Count == 0)\n {\n suitableItems.Add(\u0022No results found\u0022);\n }\n sender.ItemsSource = suitableItems;\n }\n}\n\n// Handle user selecting an item, in our case just output the selected item.\nprivate void AutoSuggestBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)\n{\n SuggestionOutput.Text = args.SelectedItem.ToString();\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BasicAutosuggestBox.txt",
+ "source": "WinUIGallery/Samples/AutoSuggestBox/BasicAutosuggestBox.txt",
+ "name": "Basic Autosuggest Box"
+ }
+ },
+ {
+ "header": "An AutoSuggestBox that provides a SearchBox experience",
+ "xaml": "\u003CAutoSuggestBox PlaceholderText=\u0022Type a control name\u0022\n TextChanged=\u0022Control2_TextChanged\u0022\n QueryIcon=\u0022Find\u0022\n QuerySubmitted=\u0022Control2_QuerySubmitted\u0022\n SuggestionChosen=\u0022Control2_SuggestionChosen\u0022/\u003E",
+ "gallery": {
+ "snippet": "AutosuggestboxProvidesSearchboxExperience.txt",
+ "source": "WinUIGallery/Samples/AutoSuggestBox/AutosuggestboxProvidesSearchboxExperience.txt",
+ "name": "Provides Searchbox Experience"
+ }
+ }
+ ]
+ },
+ {
+ "id": "badgenotificationmanager",
+ "name": "Badge notifications",
+ "description": "Show numeric or icon badges on your app\u2019s taskbar icon.",
+ "details": "Badge notifications are a lightweight way to show status or alerts as small overlays on your app\u0027s taskbar icon.",
+ "apiNamespace": "Microsoft.Windows.BadgeNotifications",
+ "relatedControls": [
+ "App notifications",
+ "InfoBadge"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.Windows.BadgeNotifications",
+ "System",
+ "System.Collections.Generic"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "taskbar badge",
+ "badge",
+ "notification badge"
+ ],
+ "docs": [
+ {
+ "title": "BadgeUpdateManager - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.badgenotifications.badgenotificationmanager"
+ },
+ {
+ "title": "BadgeNotificationGlyph Enum",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.badgenotifications.badgenotificationglyph"
+ },
+ {
+ "title": "Badge notifications",
+ "uri": "https://learn.microsoft.com/windows/apps/design/shell/tiles-and-notifications/badges"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "BadgeNotificationManager",
+ "group": {
+ "id": "Shell",
+ "title": "Shell"
+ },
+ "page": "WinUIGallery/Samples/BadgeNotificationManager/BadgeNotificationManagerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/BadgeNotificationManager/BadgeNotificationManagerPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppNotification",
+ "microsoft/WinUI-Gallery#InfoBadge"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Setting badge notifications with count",
+ "code": "private void SetBadgeCountButton_Click(object sender, RoutedEventArgs e)\n{\n BadgeNotificationManager.Current.SetBadgeAsCount(5);\n}\n\nprivate void ClearBadgeButton_Click(object sender, RoutedEventArgs e)\n{\n BadgeNotificationManager.Current.ClearBadge();\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BadgeNotificationManagerSettingBadgeNotificationsCount.txt",
+ "source": "WinUIGallery/Samples/BadgeNotificationManager/BadgeNotificationManagerSettingBadgeNotificationsCount.txt",
+ "name": "Setting Badge Notifications Count"
+ }
+ },
+ {
+ "header": "Setting badge notifications with Glyph",
+ "code": "private void SetBadgeGlyphButton_Click(object sender, RoutedEventArgs e)\n{\n BadgeNotificationManager.Current.SetBadgeAsGlyph(BadgeNotificationGlyph.$(SelectedGlyph));\n}\n\nprivate void ClearBadgeButton_Click(object sender, RoutedEventArgs e)\n{\n BadgeNotificationManager.Current.ClearBadge();\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BadgeNotificationManagerSettingBadgeNotificationsGlyph.txt",
+ "source": "WinUIGallery/Samples/BadgeNotificationManager/BadgeNotificationManagerSettingBadgeNotificationsGlyph.txt",
+ "name": "Setting Badge Notifications Glyph",
+ "codePlaceholdersPresent": [
+ "SelectedGlyph"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "binding",
+ "name": "Binding",
+ "description": "Connecting UI elements to data for automatic synchronization and updates.",
+ "details": "Binding in WinUI 3 is a way to connect a property of a control to a source, such as another property, a data object, or a view model. It keeps the data synchronized between the source and the target control, enabling dynamic updates.",
+ "relatedControls": [
+ "Resources",
+ "Style",
+ "Templates"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "System",
+ "System.Collections.Generic",
+ "System.ComponentModel"
+ ],
+ "curatedKeywords": [
+ "x:Bind",
+ "data binding",
+ "INotifyPropertyChanged",
+ "ObservableCollection",
+ "TwoWay",
+ "OneWay",
+ "DataContext"
+ ],
+ "docs": [
+ {
+ "title": "Data binding",
+ "uri": "https://learn.microsoft.com/windows/apps/develop/data-binding/"
+ },
+ {
+ "title": "{x:Bind} markup extension",
+ "uri": "https://learn.microsoft.com/windows/uwp/xaml-platform/x-bind-markup-extension"
+ },
+ {
+ "title": "{Binding} markup extension",
+ "uri": "https://learn.microsoft.com/windows/uwp/xaml-platform/binding-markup-extension"
+ },
+ {
+ "title": "Binding - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.binding"
+ },
+ {
+ "title": "IValueConverter Interface - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.data.ivalueconverter"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Binding",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/Binding/BindingPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Binding/BindingPage.xaml.cs",
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Templates",
+ "microsoft/WinUI-Gallery#XamlResources",
+ "microsoft/WinUI-Gallery#XamlStyles"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Binding between controls",
+ "xaml": "\u003CGrid ColumnSpacing=\u002212\u0022\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022auto\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022auto\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022auto\u0022 /\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n\n \u003CStackPanel Spacing=\u00228\u0022 Grid.Column=\u00220\u0022\u003E\n \u003CTextBlock Text=\u0022One-Way Binding\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n \u003C!-- One-Way Binding: The target TextBox mirrors the text entered in the SourceTextBox, but any change in the target is not reflected back to the source --\u003E\n \u003CTextBox x:Name=\u0022SourceTextBoxOneWay\u0022 Width=\u0022200\u0022 HorizontalAlignment=\u0022Left\u0022 PlaceholderText=\u0022Enter text here\u0022 /\u003E\n \u003CTextBox x:Name=\u0022TargetTextBoxOneWay\u0022 Width=\u0022200\u0022 HorizontalAlignment=\u0022Left\u0022 PlaceholderText=\u0022Mirrors above text\u0022\n Text=\u0022{x:Bind SourceTextBoxOneWay.Text, Mode=OneWay}\u0022 /\u003E\n \u003C/StackPanel\u003E\n\n \u003CAppBarSeparator Grid.Column=\u00221\u0022 /\u003E\n\n \u003CStackPanel Spacing=\u00228\u0022 Grid.Column=\u00222\u0022\u003E\n \u003CTextBlock Text=\u0022Two-Way Binding\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n \u003C!-- Two-Way Binding: Changes in the SourceTextBox are automatically reflected in the TargetTextBox, and vice versa --\u003E\n \u003CTextBox x:Name=\u0022SourceTextBoxTwoWay\u0022 Width=\u0022200\u0022 HorizontalAlignment=\u0022Left\u0022 PlaceholderText=\u0022Enter text here\u0022 /\u003E\n \u003CTextBox x:Name=\u0022TargetTextBoxTwoWay\u0022 Width=\u0022200\u0022 HorizontalAlignment=\u0022Left\u0022 PlaceholderText=\u0022Mirrors and edits above text\u0022\n Text=\u0022{x:Bind SourceTextBoxTwoWay.Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "BindingControls.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingControls.txt",
+ "name": "Controls"
+ }
+ },
+ {
+ "header": "Binding to a property in code-behind",
+ "xaml": "\u003CTextBlock\n Text=\u0022{x:Bind GreetingMessage}\u0022\n FontSize=\u002224\u0022\n HorizontalAlignment=\u0022Center\u0022\n VerticalAlignment=\u0022Center\u0022 /\u003E",
+ "code": "// Code-behind\npublic string GreetingMessage { get; set; } = \u0022Hello, WinUI 3!\u0022;",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BindingPropertyCodeBehind.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingPropertyCodeBehind.txt",
+ "name": "Property Code Behind"
+ }
+ },
+ {
+ "header": "Using a function in x:Bind",
+ "xaml": "\u003CDatePicker x:Name=\u0022DatePickerControl\u0022 Header=\u0022Select a date\u0022 /\u003E\n\u003CTextBlock Text=\u0022{x:Bind FormatDate(DatePickerControl.SelectedDate), Mode=OneWay}\u0022 /\u003E",
+ "code": "public string FormatDate(DateTimeOffset? date)\n{\n if (date.HasValue)\n {\n return \u0022Selected date is: \u0022 \u002B date.Value.ToString(\u0022dddd, MMMM d, yyyy\u0022);\n }\n else\n {\n return \u0022No date selected\u0022;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BindingFunctionBind.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingFunctionBind.txt",
+ "name": "Function Bind"
+ }
+ },
+ {
+ "header": "Using a converter in Binding",
+ "code": "using Microsoft.UI.Xaml.Data;\nusing Microsoft.UI.Xaml;\n\nnamespace YourNamespace\n{\n public class EmptyStringToVisibilityConverter : IValueConverter\n {\n // Visibility value when the input string is empty or null\n public Visibility EmptyValue { get; set; } = Visibility.Collapsed;\n\n // Visibility value when the input string is non-empty\n public Visibility NonEmptyValue { get; set; } = Visibility.Visible;\n\n public object Convert(object value, Type targetType, object parameter, string language)\n {\n // Return EmptyValue if the input is null or empty, otherwise NonEmptyValue\n return value is string stringValue \u0026\u0026 !string.IsNullOrEmpty(stringValue) \n ? NonEmptyValue \n : EmptyValue;\n }\n\n public object ConvertBack(object value, Type targetType, object parameter, string language)\n {\n // ConvertBack is not needed and not implemented in this case\n throw new NotImplementedException();\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ConverterBinding.txt",
+ "source": "WinUIGallery/Samples/Binding/ConverterBinding.txt",
+ "name": "Converter Binding",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "Binding to a view model",
+ "xaml": "\u003CTextBlock Text=\u0022Title:\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n\u003CTextBlock Text=\u0022{Binding Title}\u0022 FontSize=\u002216\u0022 /\u003E\n\n\u003CTextBlock Text=\u0022Description:\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n\u003CTextBlock Text=\u0022{Binding Description}\u0022 FontSize=\u002216\u0022 /\u003E",
+ "code": "using System.ComponentModel; // For INotifyPropertyChanged interface.\nusing Microsoft.UI.Xaml.Controls; // For Page and other WinUI controls.\n\nnamespace YourNamespace\n{\n // Main page class\n public sealed partial class YourPage : Page\n {\n // Property to hold the ViewModel instance.\n public ExampleViewModel ViewModel { get; set; }\n\n public YourPage()\n {\n this.InitializeComponent();\n\n // Initialize the ViewModel with sample data.\n ViewModel = new ExampleViewModel\n {\n Title = \u0022Welcome to WinUI 3\u0022, // Set initial value for Title.\n Description = \u0022This is an example of binding to a view model.\u0022, // Set initial value for Description.\n };\n\n // Set the DataContext of the page to the ViewModel.\n // This makes the ViewModel properties available for binding in XAML.\n DataContext = ViewModel;\n }\n }\n\n // ViewModel class implementing INotifyPropertyChanged for data binding.\n public class ExampleViewModel : INotifyPropertyChanged\n {\n // Backing field for Title property.\n private string _title = string.Empty;\n\n // Backing field for Description property.\n private string _description = string.Empty;\n\n // Property for Title with change notification.\n public string Title\n {\n get =\u003E _title; // Return the current value of _title.\n set\n {\n if (_title != value) // Check if the new value is different.\n {\n _title = value; // Update the backing field.\n OnPropertyChanged(nameof(Title)); // Notify the UI of the change.\n }\n }\n }\n\n // Property for Description with change notification.\n public string Description\n {\n get =\u003E _description; // Return the current value of _description.\n set\n {\n if (_description != value) // Check if the new value is different.\n {\n _description = value; // Update the backing field.\n OnPropertyChanged(nameof(Description)); // Notify the UI of the change.\n }\n }\n }\n\n // Event to notify subscribers (UI elements) of property changes.\n public event PropertyChangedEventHandler? PropertyChanged;\n\n // Method to raise the PropertyChanged event.\n // This notifies the UI to update the bound control.\n protected void OnPropertyChanged(string propertyName)\n {\n PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BindingViewModel.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingViewModel.txt",
+ "name": "View Model"
+ }
+ },
+ {
+ "header": "Binding with TargetNullValue",
+ "xaml": "\u003C!--TargetNullValue property help handle scenarios where the binding source is null--\u003E\n\u003CTextBlock Text=\u0022{Binding ViewModel.NullString, Mode=OneWay, TargetNullValue=\u0027Anonymous User\u0027}\u0022 /\u003E",
+ "code": "public YourPage()\n{\n this.InitializeComponent();\n\n ViewModel = new ExampleViewModel\n {\n NullString = null\n };\n \n DataContext = ViewModel;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BindingTargetnullvalue.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingTargetnullvalue.txt",
+ "name": "Targetnullvalue"
+ }
+ },
+ {
+ "header": "Binding a collection with data templates",
+ "xaml": "\u003CListView\n x:Name=\u0022ListDetailListView\u0022\n ItemsSource=\u0022{x:Bind Items}\u0022\n SelectedIndex=\u00220\u0022\n SelectionMode=\u0022Single\u0022\u003E\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022local:ListDetailItem\u0022\u003E\n \u003CStackPanel Padding=\u00224\u0022 Spacing=\u00222\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Title}\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n \u003CTextBlock Text=\u0022{x:Bind DateCreatedFormatted}\u0022\n Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E\n\n\u003C!-- Detail panel bound to the selected item --\u003E\n\u003CStackPanel DataContext=\u0022{x:Bind ListDetailListView.SelectedItem, Mode=OneWay}\u0022\u003E\n \u003CTextBlock Text=\u0022{Binding Title}\u0022 FontSize=\u002220\u0022 FontWeight=\u0022SemiBold\u0022 /\u003E\n \u003CTextBlock Text=\u0022{Binding DateCreatedFormatted}\u0022\n Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 /\u003E\n \u003CTextBlock Text=\u0022{Binding Text}\u0022 TextWrapping=\u0022Wrap\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "code": "public class ListDetailItem\n{\n public int Id { get; set; }\n public string Title { get; set; }\n public string Text { get; set; }\n public DateTime DateCreated { get; set; }\n public string DateCreatedFormatted =\u003E DateCreated.ToString(\u0022MMM d, yyyy h:mm tt\u0022);\n}\n\n// In your page class:\npublic List\u003CListDetailItem\u003E Items { get; set; }\n\npublic MyPage()\n{\n this.InitializeComponent();\n\n Items = new List\u003CListDetailItem\u003E\n {\n new ListDetailItem\n {\n Id = 0,\n Title = \u0022Item 1\u0022,\n Text = \u0022Lorem ipsum dolor sit amet...\u0022,\n DateCreated = new DateTime(2025, 6, 15, 9, 30, 0)\n },\n // Add more items...\n };\n}",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "BindingCollectionDataTemplates.txt",
+ "source": "WinUIGallery/Samples/Binding/BindingCollectionDataTemplates.txt",
+ "name": "Collection Data Templates"
+ }
+ }
+ ]
+ },
+ {
+ "id": "border",
+ "name": "Border",
+ "description": "A container control that draws a boundary line, background, or both, around another object.",
+ "details": "Use a Border control to draw a boundary line, background, or both, around another object. A Border can contain only one child object.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Canvas",
+ "Grid",
+ "StackPanel",
+ "VariableSizedWrapGrid",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "outline",
+ "frame",
+ "background"
+ ],
+ "docs": [
+ {
+ "title": "Border - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.border"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Border",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/Border/BorderPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Border/BorderPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#VariableSizedWrapGrid"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A Border around a TextBlock.",
+ "xaml": "\u003CBorder\u003E\n \u003CTextBlock Text=\u0022Text inside a border\u0022 FontSize=\u002218\u0022 Foreground=\u0022Black\u0022 /\u003E\n\u003C/Border\u003E",
+ "gallery": {
+ "snippet": "BorderAroundTextblock.txt",
+ "source": "WinUIGallery/Samples/Border/BorderAroundTextblock.txt",
+ "name": "Around Textblock",
+ "xamlPlaceholdersDropped": [
+ "BorderThickness",
+ "BorderBrush",
+ "Background"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "breadcrumbbar",
+ "name": "BreadcrumbBar",
+ "description": "Shows the trail of navigation taken to the current location.",
+ "details": "The BreadcrumbBar control provides a common horizontal layout to display the trail of navigation taken to the current location. Resize to see the nodes crumble, starting at the root.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NavigationView",
+ "Pivot",
+ "TabView"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "System.Collections.Generic",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "navigation trail",
+ "path"
+ ],
+ "docs": [
+ {
+ "title": "BreadcrumbBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.breadcrumbbar"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/breadcrumbbar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "BreadcrumbBar",
+ "group": {
+ "id": "Navigation",
+ "title": "Navigation"
+ },
+ "page": "WinUIGallery/Samples/BreadcrumbBar/BreadcrumbBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/BreadcrumbBar/BreadcrumbBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#NavigationView",
+ "microsoft/WinUI-Gallery#Pivot",
+ "microsoft/WinUI-Gallery#TabView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A BreadcrumbBar control",
+ "xaml": "\u003CBreadcrumbBar x:Name=\u0022BreadcrumbBar1\u0022/\u003E",
+ "code": "BreadcrumbBar1.ItemsSource = new string[] { \u0022Home\u0022, \u0022Documents\u0022, \u0022Design\u0022, \u0022Northwind\u0022, \u0022Images\u0022, \u0022Folder1\u0022, \u0022Folder2\u0022, \u0022Folder3\u0022 };",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BreadcrumbbarControl.txt",
+ "source": "WinUIGallery/Samples/BreadcrumbBar/BreadcrumbbarControl.txt",
+ "name": "Control"
+ }
+ },
+ {
+ "header": "BreadCrumbBar Control with Custom DataTemplate",
+ "xaml": "\u003CBreadcrumbBar x:Name=\u0022BreadcrumbBar2\u0022\u003E\n \u003CBreadcrumbBar.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022l:Folder\u0022\u003E\n \u003CBreadcrumbBarItem Content=\u0022{Binding}\u0022 AutomationProperties.Name=\u0022{Binding Name}\u0022\u003E\n \u003CBreadcrumbBarItem.ContentTemplate\u003E\n \u003CDataTemplate\u003E\n \u003CTextBlock Text=\u0022{Binding Name}\u0022 /\u003E\n \u003C/DataTemplate\u003E\n \u003C/BreadcrumbBarItem.ContentTemplate\u003E\n \u003C/BreadcrumbBarItem\u003E\n \u003C/DataTemplate\u003E\n \u003C/BreadcrumbBar.ItemTemplate\u003E\n\u003C/BreadcrumbBar\u003E",
+ "code": "public class Folder\n{\n public string Name { get; set; }\n}\n\nBreadcrumbBar2.ItemsSource = new ObservableCollection\u003CFolder\u003E{\n new Folder { Name = \u0022Home\u0022},\n new Folder { Name = \u0022Folder1\u0022 },\n new Folder { Name = \u0022Folder2\u0022 },\n new Folder { Name = \u0022Folder3\u0022 },\n};\nBreadcrumbBar2.ItemClicked \u002B= BreadcrumbBar2_ItemClicked;\n\nprivate void BreadcrumbBar2_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemClickedEventArgs args)\n{\n var items = BreadcrumbBar2.ItemsSource as ObservableCollection\u003CFolder\u003E;\n for (int i = items.Count - 1; i \u003E= args.Index \u002B 1; i--)\n {\n items.RemoveAt(i);\n }\n}",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:l=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "BreadcrumbbarControlCustomDatatemplate.txt",
+ "source": "WinUIGallery/Samples/BreadcrumbBar/BreadcrumbbarControlCustomDatatemplate.txt",
+ "name": "Control Custom Datatemplate"
+ }
+ }
+ ]
+ },
+ {
+ "id": "button",
+ "name": "Button",
+ "description": "A control that responds to user input and raises a Click event.",
+ "details": "The Button control provides a Click event to respond to user input from a touch, mouse, keyboard, stylus, or other input device. You can put different kinds of content in a button, such as text or an image, or you can restyle a button to give it a new look.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ToggleButton",
+ "RepeatButton",
+ "HyperlinkButton",
+ "AppBarButton"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "curatedKeywords": [
+ "click",
+ "push button",
+ "command",
+ "cta",
+ "call to action"
+ ],
+ "docs": [
+ {
+ "title": "Button - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.button"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Button",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/Button/ButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Button/ButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#HyperlinkButton",
+ "microsoft/WinUI-Gallery#RepeatButton",
+ "microsoft/WinUI-Gallery#ToggleButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple Button with text content.",
+ "xaml": "\u003CButton Content=\u0022Standard XAML button\u0022 Click=\u0022Button_Click\u0022 /\u003E",
+ "code": "private void Button_Click(object sender, RoutedEventArgs e)\n{\n // Handle button click\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ButtonSimple.txt",
+ "source": "WinUIGallery/Samples/Button/ButtonSimple.txt",
+ "name": "Simple"
+ }
+ },
+ {
+ "header": "A Button with graphical content.",
+ "xaml": "\u003CButton Content=\u0022Button\u0022 Click=\u0022Button_Click\u0022 AutomationProperties.Name=\u0022Pie\u0022\u003E\n \u003CImage Source=\u0022/Assets/SampleMedia/Slices.png\u0022 AutomationProperties.Name=\u0022Slice\u0022/\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "ButtonWithImage.txt",
+ "source": "WinUIGallery/Samples/Button/ButtonWithImage.txt",
+ "name": "With Image"
+ }
+ },
+ {
+ "header": "Built-in styles applied to Button.",
+ "xaml": "\u003CButton Style=\u0022{StaticResource AccentButtonStyle}\u0022 Content=\u0022Accent style button\u0022/\u003E\n\u003CButton Style=\u0022{StaticResource SubtleButtonStyle}\u0022 Content=\u0022Subtle style button\u0022/\u003E",
+ "gallery": {
+ "snippet": "ButtonBuiltInStyles.txt",
+ "source": "WinUIGallery/Samples/Button/ButtonBuiltInStyles.txt",
+ "name": "Built In Styles"
+ }
+ },
+ {
+ "header": "Wrapping Buttons with large content",
+ "xaml": "\u003CStackPanel\u003E\n \u003CTextBlock Text=\u0022The following buttons\u0027 content may get clipped if we don\u0027t pay careful attention to their layout containers.\u0022 Margin=\u00220,0,0,8\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003CTextBlock Text=\u0022One option to mitigate clipped content is to place Buttons underneath each other, allowing for more space to grow horizontally:\u0022 Margin=\u00220,0,0,8\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003CButton HorizontalAlignment=\u0022Stretch\u0022 Margin=\u00220,0,0,5\u0022\u003EThis is some text that is too long and will get cut off\u003C/Button\u003E\n \u003CButton HorizontalAlignment=\u0022Stretch\u0022\u003EThis is another text that would result in being cut off\u003C/Button\u003E\n\n \u003CTextBlock Text=\u0022Another option is to explicitly wrap the Button\u0027s content\u0022 Margin=\u00220,8,0,8\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022 HorizontalAlignment=\u0022Center\u0022\u003E\n \u003CButton MaxWidth=\u0022240\u0022 Margin=\u00220,0,8,0\u0022\u003E\n \u003CTextBlock Text=\u0022This is some text that is too long and will get cut off\u0022 TextWrapping=\u0022WrapWholeWords\u0022/\u003E\n \u003C/Button\u003E\n \u003CButton MaxWidth=\u0022240\u0022\u003E\n \u003CTextBlock Text=\u0022This is another text that would result in being cut off\u0022 TextWrapping=\u0022WrapWholeWords\u0022/\u003E\n \u003C/Button\u003E\n \u003C/StackPanel\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "ButtonWrapping.txt",
+ "source": "WinUIGallery/Samples/Button/ButtonWrapping.txt",
+ "name": "Wrapping"
+ }
+ }
+ ]
+ },
+ {
+ "id": "calendardatepicker",
+ "name": "CalendarDatePicker",
+ "description": "A control that lets users pick a date value using a calendar.",
+ "details": "A control that lets users pick a date value using a calendar.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "DatePicker",
+ "CalendarView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "date picker"
+ ],
+ "docs": [
+ {
+ "title": "CalendarDatePicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.calendardatepicker"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/calendar-date-picker"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CalendarDatePicker",
+ "group": {
+ "id": "DateAndTime",
+ "title": "Date \u0026 time"
+ },
+ "page": "WinUIGallery/Samples/CalendarDatePicker/CalendarDatePickerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CalendarDatePicker/CalendarDatePickerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CalendarView",
+ "microsoft/WinUI-Gallery#DatePicker"
+ ]
+ },
+ "samples": [
+ {
+ "header": "CalendarDatePicker with a header and placeholder text.",
+ "xaml": "\u003CCalendarDatePicker PlaceholderText=\u0022Pick a date\u0022 Header=\u0022Calendar\u0022 /\u003E",
+ "gallery": {
+ "snippet": "CalendardatepickerHeaderPlaceholderText.txt",
+ "source": "WinUIGallery/Samples/CalendarDatePicker/CalendardatepickerHeaderPlaceholderText.txt",
+ "name": "Header Placeholder Text"
+ }
+ }
+ ]
+ },
+ {
+ "id": "calendarview",
+ "name": "CalendarView",
+ "description": "A control that presents a calendar for a user to choose a date from.",
+ "details": "CalendarView shows a larger view for showing and selecting dates. DatePicker by contrast has a compact view with inline selection.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "CalendarDatePicker",
+ "DatePicker",
+ "TimePicker"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "date",
+ "month view"
+ ],
+ "docs": [
+ {
+ "title": "CalendarView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.calendarview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/calendar-view"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CalendarView",
+ "group": {
+ "id": "DateAndTime",
+ "title": "Date \u0026 time"
+ },
+ "page": "WinUIGallery/Samples/CalendarView/CalendarViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CalendarView/CalendarViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CalendarDatePicker",
+ "microsoft/WinUI-Gallery#DatePicker",
+ "microsoft/WinUI-Gallery#TimePicker"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic calendar view.",
+ "xaml": "\u003CCalendarView\n IsGroupLabelVisible=\u0022True\u0022\n IsOutOfScopeEnabled=\u0022True\u0022\n CalendarIdentifier=\u0022{x:Bind calendarIdentifier.SelectedValue, Mode=OneWay}\u0022 /\u003E",
+ "gallery": {
+ "snippet": "BasicCalendarView.txt",
+ "source": "WinUIGallery/Samples/CalendarView/BasicCalendarView.txt",
+ "name": "Basic Calendar View",
+ "xamlPlaceholdersDropped": [
+ "SelectionMode",
+ "Language"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "canvas",
+ "name": "Canvas",
+ "description": "A layout panel that supports absolute positioning of child elements relative to the top left corner of the canvas.",
+ "details": "The Canvas provides absolute positioning of controls or content. Content is positioned relative to the Canvas using the Canvas.Top and Canvas.Left attached properties.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Border",
+ "Grid",
+ "StackPanel",
+ "VariableSizedWrapGrid",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "absolute position",
+ "coordinates"
+ ],
+ "docs": [
+ {
+ "title": "Canvas - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.canvas"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/layout-panels"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Canvas",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/Canvas/CanvasPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Canvas/CanvasPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Border",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#VariableSizedWrapGrid"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A Canvas control.",
+ "xaml": "\u003CCanvas Width=\u0022120\u0022 Height=\u0022120\u0022 Background=\u0022Gray\u0022\u003E\n \u003CRectangle Fill=\u0022Red\u0022 /\u003E\n \u003CRectangle Fill=\u0022Blue\u0022 Canvas.Left=\u002220\u0022 Canvas.Top=\u002220\u0022 Canvas.ZIndex=\u00221\u0022 /\u003E\n \u003CRectangle Fill=\u0022Green\u0022 Canvas.Left=\u002240\u0022 Canvas.Top=\u002240\u0022 Canvas.ZIndex=\u00222\u0022 /\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022 Canvas.Left=\u002260\u0022 Canvas.Top=\u002260\u0022 Canvas.ZIndex=\u00223\u0022 /\u003E\n\u003C/Canvas\u003E",
+ "gallery": {
+ "snippet": "CanvasControl.txt",
+ "source": "WinUIGallery/Samples/Canvas/CanvasControl.txt",
+ "name": "Control",
+ "xamlPlaceholdersDropped": [
+ "Left",
+ "Top",
+ "Z"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "captureelementpreview",
+ "name": "Capture Element / Camera Preview",
+ "description": "A sample for doing a camera preview.",
+ "details": "You can use a MediaPlayerElement control to show a camera preview with a MediaCapture object.",
+ "relatedControls": [
+ "MediaPlayerElement",
+ "Image"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media",
+ "Microsoft.UI.Xaml.Media.Imaging",
+ "System",
+ "System.ComponentModel",
+ "System.Threading.Tasks",
+ "Windows.Foundation",
+ "Windows.Media.Capture",
+ "Windows.Media.Capture.Frames",
+ "Windows.Media.MediaProperties",
+ "Windows.Storage.Streams",
+ "Windows.System"
+ ],
+ "curatedKeywords": [
+ "camera",
+ "webcam"
+ ],
+ "docs": [
+ {
+ "title": "MediaCapture - API",
+ "uri": "https://learn.microsoft.com/uwp/api/windows.media.capture.mediacapture"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CaptureElementPreview",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/CaptureElementPreview/CaptureElementPreviewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CaptureElementPreview/CaptureElementPreviewPage.xaml.cs",
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Image",
+ "microsoft/WinUI-Gallery#MediaPlayerElement"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A MediaCapture preview displayed via a MediaPlayerElement.",
+ "xaml": "\u003CGrid RowDefinitions=\u0022Auto,*\u0022 ColumnDefinitions=\u0022*,100\u0022 MinWidth=\u0022400\u0022 MinHeight=\u0022300\u0022 RowSpacing=\u002210\u0022 ColumnSpacing=\u00224\u0022\u003E\n \u003CStackPanel Grid.Row=\u00220\u0022 Grid.Column=\u00220\u0022 Orientation=\u0022Horizontal\u0022 Spacing=\u00228\u0022\u003E\n \u003CComboBox x:Name=\u0022cameraSourceComboBox\u0022 Header=\u0022Camera source\u0022 DisplayMemberPath=\u0022DisplayName\u0022 SelectionChanged=\u0022CameraSourceComboBox_SelectionChanged\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022frameSourceName\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003CMediaPlayerElement x:Name=\u0022captureElement\u0022 Grid.Row=\u00221\u0022 Grid.Column=\u00220\u0022 Stretch=\u0022Uniform\u0022 AutoPlay=\u0022True\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022capturedText\u0022 Visibility=\u0022Collapsed\u0022 Grid.Row=\u00220\u0022 Grid.Column=\u00221\u0022 VerticalAlignment=\u0022Center\u0022 Text=\u0022Captured:\u0022 /\u003E\n \u003CGrid x:Name=\u0022captureContainer\u0022 Grid.Row=\u00221\u0022 Grid.Column=\u00221\u0022\u003E\n \u003CScrollViewer VerticalScrollMode=\u0022Enabled\u0022\u003E\n \u003CStackPanel x:Name=\u0022snapshots\u0022 Spacing=\u00222\u0022/\u003E\n \u003C/ScrollViewer\u003E\n \u003C/Grid\u003E\n\u003C/Grid\u003E",
+ "code": "using Windows.Media.Capture.Frames;\nusing Windows.Media.Capture;\n\n private MediaFrameSourceGroup mediaFrameSourceGroup;\n private MediaCapture mediaCapture;\n\n async private void StartCaptureElement()\n {\n var groups = await MediaFrameSourceGroup.FindAllAsync();\n if (groups.Count == 0)\n {\n frameSourceName.Text = \u0022No camera devices found.\u0022;\n return;\n }\n cameraSourceComboBox.ItemsSource = groups;\n cameraSourceComboBox.SelectedIndex = 0;\n }\n\n async private void CameraSourceComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)\n {\n if (cameraSourceComboBox.SelectedItem is MediaFrameSourceGroup selectedGroup)\n {\n await StartCapture(selectedGroup);\n }\n }\n\n async private Task StartCapture(MediaFrameSourceGroup sourceGroup)\n {\n if (mediaCapture != null)\n {\n captureElement.Source = null;\n mediaCapture.Dispose();\n mediaCapture = null;\n }\n\n mediaFrameSourceGroup = sourceGroup;\n frameSourceName.Text = \u0022Viewing: \u0022 \u002B mediaFrameSourceGroup.DisplayName;\n mediaCapture = new MediaCapture();\n var mediaCaptureInitializationSettings = new MediaCaptureInitializationSettings()\n {\n SourceGroup = this.mediaFrameSourceGroup,\n SharingMode = MediaCaptureSharingMode.SharedReadOnly,\n StreamingCaptureMode = StreamingCaptureMode.Video,\n MemoryPreference = MediaCaptureMemoryPreference.Cpu\n };\n await mediaCapture.InitializeAsync(mediaCaptureInitializationSettings);\n\n // Set the MediaPlayerElement\u0027s Source property to the MediaSource for the mediaCapture.\n var frameSource = mediaCapture.FrameSources[this.mediaFrameSourceGroup.SourceInfos[0].Id];\n captureElement.Source = Windows.Media.Core.MediaSource.CreateFromMediaFrameSource(frameSource);\n$(MirrorPreview) }\n\n async private void CapturePhoto_Click(object sender, RoutedEventArgs e)\n {\n // Capture a photo to a stream\n var imgFormat = ImageEncodingProperties.CreateJpeg();\n var stream = new InMemoryRandomAccessStream();\n await mediaCapture.CapturePhotoToStreamAsync(imgFormat, stream);\n stream.Seek(0);\n\n // Show the photo in an Image element\n BitmapImage bmpImage = new BitmapImage();\n await bmpImage.SetSourceAsync(stream);\n var image = new Image() { Source = bmpImage };\n snapshots.Children.Insert(0, image);\n\n capturedText.Visibility = Visibility.Visible;\n }",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CaptureElementPreviewMediacapturePreviewDisplayedVia.txt",
+ "source": "WinUIGallery/Samples/CaptureElementPreview/CaptureElementPreviewMediacapturePreviewDisplayedVia.txt",
+ "name": "Mediacapture Preview Displayed Via",
+ "codePlaceholdersPresent": [
+ "MirrorPreview"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "checkbox",
+ "name": "CheckBox",
+ "description": "A control that a user can select or clear.",
+ "details": "CheckBox controls let the user select a combination of binary options. In contrast, RadioButton controls allow the user to select from mutually exclusive options. The indeterminate state is used to indicate that an option is set for some, but not all, child options. Don\u0027t allow users to set an indeterminate state directly to indicate a third option.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "RadioButton",
+ "ToggleSwitch",
+ "ToggleButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "curatedKeywords": [
+ "tick",
+ "three state",
+ "checkmark"
+ ],
+ "docs": [
+ {
+ "title": "CheckBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.checkbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/checkbox"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CheckBox",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/CheckBox/CheckBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CheckBox/CheckBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#RadioButton",
+ "microsoft/WinUI-Gallery#ToggleButton",
+ "microsoft/WinUI-Gallery#ToggleSwitch"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A 2-state CheckBox.",
+ "xaml": "\u003CCheckBox Content=\u0022Two-state CheckBox\u0022\n Checked=\u0022TwoState_Checked\u0022\n Unchecked=\u0022TwoState_Unchecked\u0022 /\u003E",
+ "gallery": {
+ "snippet": "CheckBoxTwoState.txt",
+ "source": "WinUIGallery/Samples/CheckBox/CheckBoxTwoState.txt",
+ "name": "Two State"
+ }
+ },
+ {
+ "header": "A 3-state CheckBox.",
+ "xaml": "\u003CCheckBox Content=\u0022Three-state CheckBox\u0022\n IsThreeState=\u0022True\u0022\n Checked=\u0022ThreeState_Checked\u0022\n Unchecked=\u0022ThreeState_Unchecked\u0022\n Indeterminate=\u0022ThreeState_Indeterminate\u0022 /\u003E",
+ "gallery": {
+ "snippet": "CheckBoxThreeState.txt",
+ "source": "WinUIGallery/Samples/CheckBox/CheckBoxThreeState.txt",
+ "name": "Three State"
+ }
+ },
+ {
+ "header": "Using a 3-state CheckBox.",
+ "xaml": "\u003CStackPanel\u003E\n \u003CCheckBox x:Name=\u0022OptionsAllCheckBox\u0022 Content=\u0022Select all\u0022 IsThreeState=\u0022True\u0022\n Checked=\u0022SelectAll_Checked\u0022 Unchecked=\u0022SelectAll_Unchecked\u0022\n Indeterminate=\u0022SelectAll_Indeterminate\u0022 /\u003E\n \u003CCheckBox x:Name=\u0022Option1CheckBox\u0022 Content=\u0022Option 1\u0022 Margin=\u002224,0,0,0\u0022 Checked=\u0022Option_Checked\u0022 Unchecked=\u0022Option_Unchecked\u0022 /\u003E\n \u003CCheckBox x:Name=\u0022Option2CheckBox\u0022 Content=\u0022Option 2\u0022 Margin=\u002224,0,0,0\u0022 Checked=\u0022Option_Checked\u0022 Unchecked=\u0022Option_Unchecked\u0022 IsChecked=\u0022True\u0022 /\u003E\n \u003CCheckBox x:Name=\u0022Option3CheckBox\u0022 Content=\u0022Option 3\u0022 Margin=\u002224,0,0,0\u0022 Checked=\u0022Option_Checked\u0022 Unchecked=\u0022Option_Unchecked\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "CheckBoxSelectAll.txt",
+ "source": "WinUIGallery/Samples/CheckBox/CheckBoxSelectAll.txt",
+ "name": "Select All"
+ }
+ }
+ ]
+ },
+ {
+ "id": "clipboard",
+ "name": "Clipboard",
+ "description": "Copy and paste text, images, and files to and from the system Clipboard.",
+ "details": "Use the Clipboard API to copy and paste text, images, and files. Configure clipboard history and roaming options, monitor content changes, and inspect available formats.",
+ "apiNamespace": "Windows.ApplicationModel.DataTransfer",
+ "relatedControls": [
+ "Storage pickers"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media.Imaging",
+ "Microsoft.Windows.Storage.Pickers",
+ "System",
+ "System.Collections.Generic",
+ "System.Text",
+ "System.Threading.Tasks",
+ "Windows.ApplicationModel.DataTransfer",
+ "Windows.Storage.Streams"
+ ],
+ "curatedKeywords": [
+ "copy",
+ "paste",
+ "cut"
+ ],
+ "docs": [
+ {
+ "title": "Clipboard - API",
+ "uri": "https://learn.microsoft.com/uwp/api/windows.applicationmodel.datatransfer.clipboard"
+ },
+ {
+ "title": "ClipboardContentOptions - API",
+ "uri": "https://learn.microsoft.com/uwp/api/windows.applicationmodel.datatransfer.clipboardcontentoptions"
+ },
+ {
+ "title": "Copy and paste - Guide",
+ "uri": "https://learn.microsoft.com/windows/apps/develop/communication/copy-and-paste"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Clipboard",
+ "group": {
+ "id": "System",
+ "title": "System"
+ },
+ "page": "WinUIGallery/Samples/Clipboard/ClipboardPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Clipboard/ClipboardPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#StoragePickers"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Copy text to the Clipboard",
+ "xaml": "\u003CButton Content=\u0022Copy Text to the Clipboard\u0022 Click=\u0022CopyText_Click\u0022/\u003E",
+ "code": "private void CopyText_Click(object sender, RoutedEventArgs args)\n{\n\tvar package = new DataPackage();\n\tpackage.SetText(\u0022Copy this text\u0022);\n\tClipboard.SetContent(package);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CopyTextClipboard.txt",
+ "source": "WinUIGallery/Samples/Clipboard/CopyTextClipboard.txt",
+ "name": "Copy Text Clipboard"
+ }
+ },
+ {
+ "header": "Paste text from the Clipboard",
+ "xaml": "\u003CButton Content=\u0022Paste Text from the Clipboard\u0022 Click=\u0022PasteText_Click\u0022/\u003E",
+ "code": "private async void PasteText_Click(object sender, RoutedEventArgs args)\n{\n\tvar package = Clipboard.GetContent();\n\tif (package.Contains(StandardDataFormats.Text))\n\t{\n\t\tvar text = await package.GetTextAsync();\n\t}\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "PasteTextClipboard.txt",
+ "source": "WinUIGallery/Samples/Clipboard/PasteTextClipboard.txt",
+ "name": "Paste Text Clipboard"
+ }
+ },
+ {
+ "header": "Copy and paste an image",
+ "code": "private void CopyImage_Click(object sender, RoutedEventArgs args)\n{\n var package = new DataPackage();\n var imageUri = new Uri(\u0022ms-appx:///Assets/SampleMedia/rainier.jpg\u0022);\n package.SetBitmap(RandomAccessStreamReference.CreateFromUri(imageUri));\n Clipboard.SetContent(package);\n}\n\nprivate async void PasteImage_Click(object sender, RoutedEventArgs args)\n{\n var package = Clipboard.GetContent();\n if (package.Contains(StandardDataFormats.Bitmap))\n {\n var imageReference = await package.GetBitmapAsync();\n using (var imageStream = await imageReference.OpenReadAsync())\n {\n var bitmapImage = new BitmapImage();\n bitmapImage.SetSource(imageStream);\n PastedImage.Source = bitmapImage;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ClipboardCopyPasteImage.txt",
+ "source": "WinUIGallery/Samples/Clipboard/ClipboardCopyPasteImage.txt",
+ "name": "Copy Paste Image"
+ }
+ },
+ {
+ "header": "Copy and paste files",
+ "code": "private async void CopyFiles_Click(object sender, RoutedEventArgs args)\n{\n var filePicker = new FileOpenPicker\n {\n ViewMode = PickerViewMode.List,\n FileTypeFilter = { \u0022*\u0022 }\n };\n\n // Initialize the picker with the current window handle (required in WinUI 3)\n var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);\n WinRT.Interop.InitializeWithWindow.Initialize(filePicker, hwnd);\n\n var storageItems = await filePicker.PickMultipleFilesAsync();\n if (storageItems.Count \u003E 0)\n {\n var package = new DataPackage();\n package.SetStorageItems(storageItems);\n package.RequestedOperation = DataPackageOperation.Copy;\n Clipboard.SetContent(package);\n }\n}\n\nprivate async void PasteFiles_Click(object sender, RoutedEventArgs args)\n{\n var package = Clipboard.GetContent();\n if (package.Contains(StandardDataFormats.StorageItems))\n {\n var storageItems = await package.GetStorageItemsAsync();\n var operation = package.RequestedOperation;\n // Display the file names and the requested operation\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ClipboardCopyPasteFiles.txt",
+ "source": "WinUIGallery/Samples/Clipboard/ClipboardCopyPasteFiles.txt",
+ "name": "Copy Paste Files"
+ }
+ },
+ {
+ "header": "Clipboard history and roaming options",
+ "code": "private void CopyWithOptions_Click(object sender, RoutedEventArgs args)\n{\n var package = new DataPackage();\n package.SetText(\u0022Text with clipboard options\u0022);\n\n var options = new ClipboardContentOptions();\n options.IsAllowedInHistory = true;\n options.IsRoamable = true;\n\n Clipboard.SetContentWithOptions(package, options);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ClipboardHistoryRoamingOptions.txt",
+ "source": "WinUIGallery/Samples/Clipboard/ClipboardHistoryRoamingOptions.txt",
+ "name": "History Roaming Options"
+ }
+ },
+ {
+ "header": "Other clipboard operations",
+ "code": "// Show available formats on the clipboard\nvar package = Clipboard.GetContent();\nforeach (var format in package.AvailableFormats)\n{\n // Display each format\n}\n\n// Clear the clipboard\nClipboard.Clear();\n\n// Register for clipboard content changes\nClipboard.ContentChanged \u002B= (s, e) =\u003E\n{\n // Handle clipboard content change\n};",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "OtherClipboardOperations.txt",
+ "source": "WinUIGallery/Samples/Clipboard/OtherClipboardOperations.txt",
+ "name": "Other Clipboard Operations"
+ }
+ }
+ ]
+ },
+ {
+ "id": "color",
+ "name": "Color",
+ "description": "Balanced color design creates clarity and aesthetic harmony.",
+ "curatedKeywords": [
+ "palette",
+ "brush",
+ "accent color",
+ "theme color"
+ ],
+ "docs": [
+ {
+ "title": "Colors in Windows 11",
+ "uri": "https://learn.microsoft.com/windows/apps/design/signature-experiences/color"
+ },
+ {
+ "title": "Windows UI Kit (Figma)",
+ "uri": "https://aka.ms/WinUI/3.0-figma-toolkit"
+ },
+ {
+ "title": "WinUI Theme Resources (GitHub)",
+ "uri": "https://github.com/microsoft/microsoft-ui-xaml/blob/main/controls/dev/CommonStyles/Common_themeresources_any.xaml"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Color",
+ "group": {
+ "id": "DesignItem",
+ "title": "Design"
+ },
+ "page": "WinUIGallery/Samples/Color/ColorPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Color/ColorPage.xaml.cs"
+ },
+ "samples": []
+ },
+ {
+ "id": "colorpicker",
+ "name": "ColorPicker",
+ "description": "A control that displays a selectable color spectrum.",
+ "details": "A selectable color spectrum.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ComboBox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "color spectrum",
+ "color wheel",
+ "RGB",
+ "hex"
+ ],
+ "docs": [
+ {
+ "title": "ColorPicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.ColorPicker"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/color-picker"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ColorPicker",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/ColorPicker/ColorPickerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ColorPicker/ColorPickerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ComboBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "ColorPicker Properties.",
+ "xaml": "\u003CColorPicker\n ColorSpectrumShape=\u0022Box\u0022\n IsMoreButtonVisible=\u0022False\u0022\n IsColorSliderVisible=\u0022True\u0022\n IsColorChannelTextInputVisible=\u0022True\u0022\n IsHexInputVisible=\u0022True\u0022\n IsAlphaSliderVisible=\u0022True\u0022\n IsAlphaTextInputVisible=\u0022True\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ColorPickerProperties.txt",
+ "source": "WinUIGallery/Samples/ColorPicker/ColorPickerProperties.txt",
+ "name": "Properties",
+ "xamlPlaceholdersDropped": [
+ "IsAlphaEnabled"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "combobox",
+ "name": "ComboBox",
+ "description": "A drop-down list of items a user can select from.",
+ "details": "Use a ComboBox when you need to conserve on-screen space and when users select only one option at a time. A ComboBox shows only the currently selected item.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "RadioButton",
+ "CheckBox",
+ "ListView",
+ "AutoSuggestBox",
+ "RatingControl"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector"
+ ],
+ "curatedKeywords": [
+ "dropdown",
+ "select",
+ "picker"
+ ],
+ "docs": [
+ {
+ "title": "ComboBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.combobox"
+ },
+ {
+ "title": "ComboBoxItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.comboboxitem"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/combo-box"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ComboBox",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/ComboBox/ComboBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ComboBox/ComboBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AutoSuggestBox",
+ "microsoft/WinUI-Gallery#CheckBox",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#RadioButton",
+ "microsoft/WinUI-Gallery#RatingControl"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A ComboBox with items defined inline and its width set.",
+ "xaml": "\u003CComboBox SelectionChanged=\u0022ColorComboBox_SelectionChanged\u0022 Header=\u0022Colors\u0022 PlaceholderText=\u0022Pick a color\u0022 Width=\u0022200\u0022\u003E\n \u003Cx:String\u003EBlue\u003C/x:String\u003E\n \u003Cx:String\u003EGreen\u003C/x:String\u003E\n \u003Cx:String\u003ERed\u003C/x:String\u003E\n \u003Cx:String\u003EYellow\u003C/x:String\u003E\n\u003C/ComboBox\u003E",
+ "gallery": {
+ "snippet": "ComboBoxInline.txt",
+ "source": "WinUIGallery/Samples/ComboBox/ComboBoxInline.txt",
+ "name": "Inline"
+ }
+ },
+ {
+ "header": "A ComboBox with its ItemsSource set.",
+ "xaml": "\u003CComboBox ItemsSource=\u0022{x:Bind Fonts}\u0022 DisplayMemberPath=\u0022Item1\u0022 SelectedValuePath=\u0022Item2\u0022\n Header=\u0022Font\u0022 Width=\u0022200\u0022 Loaded=\u0022Combo2_Loaded\u0022/\u003E",
+ "gallery": {
+ "snippet": "ComboBoxItemsSource.txt",
+ "source": "WinUIGallery/Samples/ComboBox/ComboBoxItemsSource.txt",
+ "name": "Items Source"
+ }
+ },
+ {
+ "header": "An editable ComboBox.",
+ "xaml": "\u003CComboBox IsEditable=\u0022True\u0022 ItemsSource=\u0022{x:Bind FontSizes}\u0022 Width=\u0022200\u0022 TextSubmitted=\u0022Combo3_TextSubmitted\u0022/\u003E",
+ "gallery": {
+ "snippet": "ComboBoxEditable.txt",
+ "source": "WinUIGallery/Samples/ComboBox/ComboBoxEditable.txt",
+ "name": "Editable"
+ }
+ }
+ ]
+ },
+ {
+ "id": "commandbar",
+ "name": "CommandBar",
+ "description": "A toolbar for displaying application-specific commands that handles layout and resizing of its contents.",
+ "details": "Command bars provide users with easy access to your app\u0027s most common tasks. Command bars can provide access to app-level or page-specific commands and can be used with any navigation pattern. By default, the command bar shows a row of icon buttons and an optional \u0022see more\u0022 button, which is represented by an ellipsis [...].",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AppBarButton",
+ "AppBarToggleButton",
+ "AppBarSeparator"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "AppBar"
+ ],
+ "curatedKeywords": [
+ "toolbar",
+ "commands",
+ "app bar"
+ ],
+ "docs": [
+ {
+ "title": "CommandBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.commandbar"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/command-bar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CommandBar",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/CommandBar/CommandBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CommandBar/CommandBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "AppBar"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#AppBarSeparator",
+ "microsoft/WinUI-Gallery#AppBarToggleButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A command bar with labels on the side free floating in a page",
+ "xaml": "\u003CCommandBar Background=\u0022Transparent\u0022 IsOpen=\u0022False\u0022 DefaultLabelPosition=\u0022Right\u0022\u003E\n \u003CAppBarButton Icon=\u0022Add\u0022 Label=\u0022Add\u0022/\u003E\n \u003CAppBarButton Icon=\u0022Edit\u0022 Label=\u0022Edit\u0022/\u003E\n \u003CAppBarButton Icon=\u0022Share\u0022 Label=\u0022Share\u0022/\u003E\n \u003CCommandBar.SecondaryCommands\u003E\n \u003CAppBarButton Icon=\u0022Setting\u0022 Label=\u0022Settings\u0022\u003E\n \u003CAppBarButton.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022I\u0022 /\u003E\n \u003C/AppBarButton.KeyboardAccelerators\u003E\n \u003C/AppBarButton\u003E\n \u003C/CommandBar.SecondaryCommands\u003E\n\u003C/CommandBar\u003E",
+ "gallery": {
+ "snippet": "CommandBarLabelsSide.txt",
+ "source": "WinUIGallery/Samples/CommandBar/CommandBarLabelsSide.txt",
+ "name": "Labels Side",
+ "xamlPlaceholdersDropped": [
+ "MultipleButtonsSecondaryCommands"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "commandbarflyout",
+ "name": "CommandBarFlyout",
+ "description": "A mini-toolbar displaying proactive commands, and an optional menu of commands.",
+ "details": "A mini-toolbar which displays a set of proactive commands, as well as a secondary menu of commands if desired.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "CommandBar",
+ "MenuFlyout",
+ "RichEditBox",
+ "TextBox",
+ "StandardUICommand",
+ "XamlUICommand"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives",
+ "Microsoft.UI.Xaml.Input",
+ "Windows.Foundation.Metadata"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "curatedKeywords": [
+ "context menu",
+ "toolbar flyout",
+ "commands"
+ ],
+ "docs": [
+ {
+ "title": "CommandBarFlyout - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.commandbarflyout"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/command-bar-flyout"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CommandBarFlyout",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/CommandBarFlyout/CommandBarFlyoutPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CommandBarFlyout/CommandBarFlyoutPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#MenuFlyout",
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#StandardUICommand",
+ "microsoft/WinUI-Gallery#TextBox",
+ "microsoft/WinUI-Gallery#XamlUICommand"
+ ]
+ },
+ "samples": [
+ {
+ "header": "CommandBarFlyout for commands on an in-app object",
+ "xaml": "\u003CPage.Resources\u003E\n \u003CCommandBarFlyout Placement=\u0022Right\u0022 x:Name=\u0022CommandBarFlyout1\u0022\u003E\n \u003CAppBarButton Label=\u0022Share\u0022 Icon=\u0022Share\u0022 ToolTipService.ToolTip=\u0022Share\u0022 Click=\u0022OnElementClicked\u0022 /\u003E\n \u003CAppBarButton Label=\u0022Save\u0022 Icon=\u0022Save\u0022 ToolTipService.ToolTip=\u0022Save\u0022 Click=\u0022OnElementClicked\u0022 /\u003E\n \u003CAppBarButton Label=\u0022Delete\u0022 Icon=\u0022Delete\u0022 ToolTipService.ToolTip=\u0022Delete\u0022 Click=\u0022OnElementClicked\u0022 /\u003E\n \u003CCommandBarFlyout.SecondaryCommands\u003E\n \u003CAppBarButton x:Name=\u0022ResizeButton1\u0022 Label=\u0022Resize\u0022 Click=\u0022OnElementClicked\u0022 /\u003E\n \u003CAppBarButton x:Name=\u0022MoveButton1\u0022 Label=\u0022Move\u0022 Click=\u0022OnElementClicked\u0022 /\u003E\n \u003C/CommandBarFlyout.SecondaryCommands\u003E\n \u003C/CommandBarFlyout\u003E\n\u003C/Page.Resources\u003E\n\n\u003CButton x:Name=\u0022myImageButton\u0022 AutomationProperties.Name=\u0022mountain\u0022 Padding=\u00220\u0022\n Click=\u0022MyImageButton_Click\u0022 ContextRequested=\u0022MyImageButton_ContextRequested\u0022 \u003E\n \u003CImage x:Name=\u0022Image1\u0022 Height=\u0022300\u0022 Source=\u0022/Assets/SampleMedia/rainier.jpg\u0022/\u003E\n\u003C/Button\u003E",
+ "code": "private void ShowMenu(bool isTransient)\n{\n FlyoutShowOptions myOption = new FlyoutShowOptions();\n myOption.ShowMode = isTransient ? FlyoutShowMode.Transient : FlyoutShowMode.Standard;\n CommandBarFlyout1.ShowAt(Image1, myOption);\n}\n\nprivate void MyImageButton_ContextRequested(Microsoft.UI.Xaml.UIElement sender, ContextRequestedEventArgs args)\n{\n // Show a context menu in standard mode\n // Focus will move to the menu\n ShowMenu(false);\n}\n\nprivate void MyImageButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)\n{\n // Show a context menu in transient mode\n // Focus will not move to the menu\n ShowMenu(true);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CommandbarflyoutCommandsAppObject.txt",
+ "source": "WinUIGallery/Samples/CommandBarFlyout/CommandbarflyoutCommandsAppObject.txt",
+ "name": "Commands App Object"
+ }
+ }
+ ]
+ },
+ {
+ "id": "compactsizing",
+ "name": "Compact Sizing",
+ "description": "How to use a Resource Dictionary to enable compact sizing.",
+ "details": "Enables the creation of compact, smaller apps by adding a style resource at the app, page or control level.",
+ "curatedKeywords": [
+ "density",
+ "compact sizing"
+ ],
+ "docs": [
+ {
+ "title": "Spacing",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/spacing"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CompactSizing",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/CompactSizing/CompactSizingPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CompactSizing/CompactSizingPage.xaml.cs",
+ "badges": [
+ "Updated"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Compact Sizing for controls",
+ "xaml": "\u003CPage.Resources\u003E\n \u003CResourceDictionary Source=\u0022ms-appx:///Microsoft.UI.Xaml/DensityStyles/Compact.xaml\u0022 /\u003E\n\u003C/Page.Resources\u003E",
+ "gallery": {
+ "snippet": "CompactSizingControls.txt",
+ "source": "WinUIGallery/Samples/CompactSizing/CompactSizingControls.txt",
+ "name": "Controls"
+ }
+ }
+ ]
+ },
+ {
+ "id": "connectedanimation",
+ "name": "Connected Animation",
+ "description": "Connected animations continue elements during page navigation and help the user maintain their context between views.",
+ "details": "Connected animations continue elements during page navigation and help the user maintain their context between views.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media.Animation",
+ "relatedControls": [
+ "Page Transitions",
+ "Theme Transitions"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media.Animation",
+ "System",
+ "System.Collections.Generic"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "connected animation",
+ "continuity",
+ "page transition"
+ ],
+ "docs": [
+ {
+ "title": "ConnectedAnimation - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.animation.connectedanimation"
+ },
+ {
+ "title": "ConnectedAnimationService - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.animation.connectedanimationservice"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/connected-animation"
+ },
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ConnectedAnimation",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/ConnectedAnimation/ConnectedAnimationPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ConnectedAnimation/ConnectedAnimationPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#PageTransition",
+ "microsoft/WinUI-Gallery#ThemeTransition"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A connected animation between a list page and a detail page",
+ "code": "// To see the source code: \n// https://github.com/microsoft/WinUI-Gallery/blob/main/WinUIGallery/ConnectedAnimationPages/CollectionPage.xaml.cs\n// https://github.com/microsoft/WinUI-Gallery/blob/main/WinUIGallery/ConnectedAnimationPages/DetailedInfoPage.xaml.cs\n\n// COLLECTION PAGE\npublic sealed partial class CollectionPage : Page\n{\n CustomDataObject? _storeditem;\n\n public CollectionPage()\n {\n this.InitializeComponent();\n\n // Ensure that the MainPage is only created once, and cached during navigation.\n this.NavigationCacheMode = NavigationCacheMode.Enabled;\n\n collection.ItemsSource = WinUIGallery.ControlPages.CustomDataObject.GetDataObjects();\n }\n\n private async void collection_Loaded(object sender, RoutedEventArgs e)\n {\n if (_storeditem != null)\n {\n // If the connected item appears outside the viewport, scroll it into view.\n collection.ScrollIntoView(_storeditem, ScrollIntoViewAlignment.Default);\n collection.UpdateLayout();\n\n // Play the second connected animation. \n ConnectedAnimation animation = ConnectedAnimationService.GetForCurrentView().GetAnimation(\u0022BackConnectedAnimation\u0022);\n if (animation != null)\n {\n // Setup the \u0022back\u0022 configuration if the API is present. \n if (ApiInformation.IsApiContractPresent(\u0022Windows.Foundation.UniversalApiContract\u0022, 7))\n {\n animation.Configuration = new DirectConnectedAnimationConfiguration();\n }\n\n await collection.TryStartConnectedAnimationAsync(animation, _storeditem, \u0022connectedElement\u0022);\n }\n\n // Set focus on the list\n collection.Focus(FocusState.Programmatic);\n }\n }\n\n private void collection_ItemClick(object sender, ItemClickEventArgs e)\n {\n // Get the collection item corresponding to the clicked item.\n if (collection.ContainerFromItem(e.ClickedItem) is ListViewItem container)\n {\n // Stash the clicked item for use later. We\u0027ll need it when we connect back from the detailpage.\n _storeditem = container.Content as CustomDataObject;\n\n // Prepare the connected animation.\n // Notice that the stored item is passed in, as well as the name of the connected element. \n // The animation will actually start on the Detailed info page.\n collection.PrepareConnectedAnimation(\u0022ForwardConnectedAnimation\u0022, _storeditem, \u0022connectedElement\u0022);\n }\n\n // Navigate to the DetailedInfoPage.\n // Note that we suppress the default animation. \n Frame.Navigate(typeof(DetailedInfoPage), _storeditem, new SuppressNavigationTransitionInfo());\n }\n}\n\n// DETAILED PAGE\npublic sealed partial class DetailedInfoPage : Page\n{\n public CustomDataObject? DetailedObject { get; set; }\n\n public DetailedInfoPage()\n {\n this.InitializeComponent();\n GoBackButton.Loaded \u002B= GoBackButton_Loaded;\n }\n\n private void GoBackButton_Loaded(object sender, RoutedEventArgs e)\n {\n // When we land in page, put focus on the back button\n GoBackButton.Focus(FocusState.Programmatic);\n\n // Scroll the back button into view so keyboard focus is not left off-screen behind\n // the surrounding scroll viewer (MAS 2.4.11 - Focus Not Obscured).\n GoBackButton.StartBringIntoView();\n }\n\n protected override void OnNavigatedTo(NavigationEventArgs e)\n {\n base.OnNavigatedTo(e);\n\n // Store the item to be used in binding to UI\n DetailedObject = e.Parameter as CustomDataObject;\n\n ConnectedAnimation imageAnimation = ConnectedAnimationService.GetForCurrentView().GetAnimation(\u0022ForwardConnectedAnimation\u0022);\n if (imageAnimation != null)\n {\n // Connected animation \u002B coordinated animation\n imageAnimation.TryStart(detailedImage, new UIElement[] { coordinatedPanel });\n\n }\n }\n\n // Create connected animation back to collection page.\n protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)\n {\n base.OnNavigatingFrom(e);\n\n ConnectedAnimationService.GetForCurrentView().PrepareToAnimate(\u0022BackConnectedAnimation\u0022, detailedImage);\n }\n\n private void BackButton_Click(object sender, RoutedEventArgs e)\n {\n Frame.GoBack();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ConnectedAnimationListPage.txt",
+ "source": "WinUIGallery/Samples/ConnectedAnimation/ConnectedAnimationListPage.txt",
+ "name": "List Page",
+ "xamlOmittedUnboundPrefixes": [
+ "local"
+ ]
+ }
+ },
+ {
+ "header": "A connected animation between elements on the same page",
+ "xaml": "\u003CGridView x:Name=\u0022collection\u0022 IsItemClickEnabled=\u0022True\u0022 ItemClick=\u0022TipsGrid_ItemClick\u0022\n HorizontalAlignment=\u0022Center\u0022 MaxWidth=\u00221400\u0022\u003E\n \u003CGridView.ItemContainerStyle\u003E\n \u003CStyle BasedOn=\u0022{StaticResource GridViewItemRevealStyle}\u0022 TargetType=\u0022GridViewItem\u0022\u003E\n \u003CStyle.Setters\u003E\n \u003CSetter Property=\u0022Margin\u0022 Value=\u00224\u0022 /\u003E\n \u003C/Style.Setters\u003E\n \u003C/Style\u003E\n \u003C/GridView.ItemContainerStyle\u003E\n \u003CGridView.ItemTemplate\u003E\n \u003CDataTemplate\u003E\n \u003CGrid x:Name=\u0022connectedElement\u0022 Width=\u0022150\u0022 Height=\u0022110\u0022\n AutomationProperties.Name=\u0022{Binding Title}\u0022 CornerRadius=\u00224\u0022\u003E\n \u003CImage Source=\u0022{Binding ImageLocation}\u0022 Stretch=\u0022UniformToFill\u0022 /\u003E\n \u003CBorder Padding=\u00228,4\u0022 VerticalAlignment=\u0022Bottom\u0022\n Background=\u0022{ThemeResource AcrylicBackgroundFillColorBaseBrush}\u0022\u003E\n \u003CTextBlock Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Text=\u0022{Binding Title}\u0022 /\u003E\n \u003C/Border\u003E\n \u003C/Grid\u003E\n \u003C/DataTemplate\u003E\n \u003C/GridView.ItemTemplate\u003E\n\u003C/GridView\u003E\n\n\u003CGrid x:Name=\u0022SmokeGrid\u0022 HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Stretch\u0022\n Background=\u0022{ThemeResource SmokeFillColorDefaultBrush}\u0022 Visibility=\u0022Collapsed\u0022\u003E\n \u003CGrid x:Name=\u0022destinationElement\u0022 Width=\u0022400\u0022 Height=\u0022320\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022\n BorderBrush=\u0022{ThemeResource CardStrokeColorDefaultBrush}\u0022 BorderThickness=\u00221\u0022\n CornerRadius=\u00228\u0022\u003E\n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022*\u0022 /\u003E\n \u003CRowDefinition Height=\u0022Auto\u0022 /\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CImage x:Name=\u0022detailImage\u0022 Grid.Row=\u00220\u0022 Stretch=\u0022UniformToFill\u0022 /\u003E\n \u003CButton Width=\u002236\u0022 Height=\u002236\u0022 Margin=\u00228\u0022\n HorizontalAlignment=\u0022Right\u0022 VerticalAlignment=\u0022Top\u0022\n AutomationProperties.Name=\u0022Close\u0022 Click=\u0022BackButton_Click\u0022\n ToolTipService.ToolTip=\u0022Close\u0022\u003E\n \u003CButton.Content\u003E\n \u003CFontIcon FontSize=\u002214\u0022 Glyph=\u0022\u0026#xE711;\u0022 /\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CStackPanel Grid.Row=\u00221\u0022 Padding=\u002216,12\u0022\n Background=\u0022{ThemeResource CardBackgroundFillColorDefaultBrush}\u0022\u003E\n \u003CTextBlock x:Name=\u0022detailTitle\u0022 Style=\u0022{ThemeResource SubtitleTextBlockStyle}\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022detailDescription\u0022 Margin=\u00220,4,0,0\u0022\n Foreground=\u0022{ThemeResource TextFillColorSecondaryBrush}\u0022\n MaxLines=\u00223\u0022 Style=\u0022{ThemeResource BodyTextBlockStyle}\u0022\n TextWrapping=\u0022Wrap\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n\u003C/Grid\u003E",
+ "code": "public sealed partial class CardPage : Page\n{\n CustomDataObject? _storedItem;\n\n public CardPage()\n {\n this.InitializeComponent();\n collection.ItemsSource = CustomDataObject.GetDataObjects(includeAllItems: true);\n }\n\n private async void BackButton_Click(object sender, RoutedEventArgs e)\n {\n ConnectedAnimation animation = ConnectedAnimationService.GetForCurrentView()\n .PrepareToAnimate(\u0022backwardsAnimation\u0022, destinationElement);\n SmokeGrid.Children.Remove(destinationElement);\n\n // Collapse the smoke when the animation completes.\n animation.Completed \u002B= Animation_Completed;\n\n // If the connected item appears outside the viewport, scroll it into view.\n collection.ScrollIntoView(_storedItem, ScrollIntoViewAlignment.Default);\n collection.UpdateLayout();\n\n animation.Configuration = new DirectConnectedAnimationConfiguration();\n\n // Play the connected animation back to the collection.\n await collection.TryStartConnectedAnimationAsync(animation, _storedItem, \u0022connectedElement\u0022);\n }\n\n private void Animation_Completed(ConnectedAnimation sender, object args)\n {\n SmokeGrid.Visibility = Visibility.Collapsed;\n SmokeGrid.Children.Add(destinationElement);\n }\n\n private void TipsGrid_ItemClick(object sender, ItemClickEventArgs e)\n {\n ConnectedAnimation? animation = null;\n\n if (collection.ContainerFromItem(e.ClickedItem) is GridViewItem container)\n {\n _storedItem = container.Content as CustomDataObject;\n animation = collection.PrepareConnectedAnimation(\u0022forwardAnimation\u0022, _storedItem, \u0022connectedElement\u0022);\n }\n\n // Update the detail view with the clicked item\u0027s data.\n if (_storedItem != null)\n {\n detailImage.Source = new BitmapImage(new Uri(\u0022ms-appx://\u0022 \u002B _storedItem.ImageLocation));\n detailTitle.Text = _storedItem.Title;\n detailDescription.Text = _storedItem.Description;\n }\n\n SmokeGrid.Visibility = Visibility.Visible;\n animation?.TryStart(destinationElement);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ConnectedAnimationElementsSame.txt",
+ "source": "WinUIGallery/Samples/ConnectedAnimation/ConnectedAnimationElementsSame.txt",
+ "name": "Elements Same"
+ }
+ },
+ {
+ "header": "A simple connected animation",
+ "code": "// Prepare animation on Source page\nprivate void NavigateButton_Click(object sender, RoutedEventArgs e)\n{\n ConnectedAnimationService.GetForCurrentView().PrepareToAnimate(\u0022ForwardConnectedAnimation\u0022, SourceElement);\n Frame.Navigate(typeof(DestinationPage), null, new SuppressNavigationTransitionInfo());\n}\n\n// Start animation on Destination page\nprotected override void OnNavigatedTo(NavigationEventArgs e)\n{\n base.OnNavigatedTo(e);\n\n var anim = ConnectedAnimationService.GetForCurrentView().GetAnimation(\u0022ForwardConnectedAnimation\u0022);\n if (anim != null)\n {\n anim.TryStart(DestinationElement);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SimpleConnectedAnimation.txt",
+ "source": "WinUIGallery/Samples/ConnectedAnimation/SimpleConnectedAnimation.txt",
+ "name": "Simple Connected Animation"
+ }
+ },
+ {
+ "header": "Connected animation with ItemsRepeater",
+ "code": "// ItemsRepeater does not have PrepareConnectedAnimation() or\n// TryStartConnectedAnimationAsync() like ListView/GridView.\n// Use ConnectedAnimationService.PrepareToAnimate() directly instead.\n\nprivate CustomDataObject _storedItem;\nprivate double _persistedScrollPosition;\n\nprivate void Repeater_ElementPrepared(ItemsRepeater sender, ItemsRepeaterElementPreparedEventArgs args)\n{\n args.Element.Tapped -= Item_Tapped;\n args.Element.Tapped \u002B= Item_Tapped;\n args.Element.KeyDown -= Item_KeyDown;\n args.Element.KeyDown \u002B= Item_KeyDown;\n}\n\nprivate void Item_Tapped(object sender, TappedRoutedEventArgs e)\n{\n NavigateToItem(sender as FrameworkElement);\n}\n\nprivate void Item_KeyDown(object sender, KeyRoutedEventArgs e)\n{\n // Activate the focused item with Enter or Space, matching list-style keyboard behavior.\n if (e.Key == VirtualKey.Enter || e.Key == VirtualKey.Space)\n {\n NavigateToItem(sender as FrameworkElement);\n e.Handled = true;\n }\n}\n\nprivate void NavigateToItem(FrameworkElement element)\n{\n if (element == null) return;\n\n _storedItem = repeater.ItemsSourceView.GetAt(\n repeater.GetElementIndex(element)) as CustomDataObject;\n\n // Find the named element in the DataTemplate and prepare the animation.\n if (FindChildByName(element, \u0022connectedElement\u0022) is UIElement source)\n {\n ConnectedAnimationService.GetForCurrentView()\n .PrepareToAnimate(\u0022ForwardConnectedAnimation\u0022, source);\n }\n\n // Save scroll position for back navigation.\n _persistedScrollPosition = scrollViewer.VerticalOffset;\n\n Frame.Navigate(typeof(DetailPage), _storedItem,\n new SuppressNavigationTransitionInfo());\n}\n\nprotected override void OnNavigatedTo(NavigationEventArgs e)\n{\n base.OnNavigatedTo(e);\n if (_storedItem == null) return;\n\n // Restore scroll position so the target element is visible.\n scrollViewer.ChangeView(null, _persistedScrollPosition, null, true);\n UpdateLayout();\n\n int index = repeater.ItemsSourceView.IndexOf(_storedItem);\n var container = repeater.TryGetElement(index) as FrameworkElement;\n\n var animation = ConnectedAnimationService.GetForCurrentView()\n .GetAnimation(\u0022BackConnectedAnimation\u0022);\n if (animation != null)\n {\n animation.Configuration = new DirectConnectedAnimationConfiguration();\n\n if (container != null\n \u0026\u0026 FindChildByName(container, \u0022connectedElement\u0022) is UIElement target)\n {\n animation.TryStart(target);\n }\n }\n\n // Return keyboard focus to the activated item for keyboard/Narrator users.\n // Focus() is available because the Grid is a UIElement with IsTabStop set.\n if (container != null)\n container.Focus(FocusState.Programmatic);\n else\n repeater.Focus(FocusState.Programmatic);\n}\n\n// Helper to find a named element within a DataTemplate.\nprivate static UIElement FindChildByName(DependencyObject parent, string name)\n{\n for (int i = 0; i \u003C VisualTreeHelper.GetChildrenCount(parent); i\u002B\u002B)\n {\n var child = VisualTreeHelper.GetChild(parent, i);\n if (child is FrameworkElement fe \u0026\u0026 fe.Name == name)\n return fe;\n var result = FindChildByName(child, name);\n if (result != null)\n return result;\n }\n return null;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ConnectedAnimationItemsrepeater.txt",
+ "source": "WinUIGallery/Samples/ConnectedAnimation/ConnectedAnimationItemsrepeater.txt",
+ "name": "Itemsrepeater",
+ "xamlOmittedUnboundPrefixes": [
+ "local"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "contentdialog",
+ "name": "ContentDialog",
+ "description": "A dialog box that can be customized to contain any XAML content.",
+ "details": "Use a ContentDialog to show relevant information or to provide a modal dialog experience that can show any XAML content.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Flyout",
+ "MenuFlyout",
+ "TeachingTip",
+ "ToolTip"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Automation.Peers",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media",
+ "System"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "modal",
+ "popup dialog",
+ "message box"
+ ],
+ "docs": [
+ {
+ "title": "ContentDialog - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.contentdialog"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/dialogs-and-flyouts/dialogs"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ContentDialog",
+ "group": {
+ "id": "DialogsAndFlyouts",
+ "title": "Dialogs \u0026 flyouts"
+ },
+ "page": "WinUIGallery/Samples/ContentDialog/ContentDialogPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ContentDialog/ContentDialogPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Flyout",
+ "microsoft/WinUI-Gallery#MenuFlyout",
+ "microsoft/WinUI-Gallery#TeachingTip",
+ "microsoft/WinUI-Gallery#ToolTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic content dialog with content.",
+ "xaml": "\u003CPage\n x:Class=\u0022WinUIGallery.ControlPages.ContentDialogContent\u0022\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:x=\u0022http://schemas.microsoft.com/winfx/2006/xaml\u0022\u003E\n\n \u003CStackPanel VerticalAlignment=\u0022Stretch\u0022 HorizontalAlignment=\u0022Stretch\u0022\u003E\n \u003C!-- Content body --\u003E\n \u003CTextBlock Text=\u0022Lorem ipsum dolor sit amet, adipisicing elit.\u0022 TextWrapping=\u0022Wrap\u0022 /\u003E\n \u003CCheckBox Content=\u0022Upload your content to the cloud.\u0022/\u003E\n \u003C/StackPanel\u003E\n\n\u003C/Page\u003E",
+ "code": "private async void ShowDialog_Click(object sender, RoutedEventArgs e)\n{\n ContentDialog dialog = new ContentDialog();\n\n // XamlRoot must be set in the case of a ContentDialog running in a Desktop app\n dialog.XamlRoot = this.XamlRoot;\n dialog.Style = Application.Current.Resources[\u0022DefaultContentDialogStyle\u0022] as Style;\n dialog.Title = \u0022Save your work?\u0022;\n dialog.PrimaryButtonText = \u0022Save\u0022;\n dialog.SecondaryButtonText = \u0022Don\u0027t Save\u0022;\n dialog.CloseButtonText = \u0022Cancel\u0022;\n dialog.DefaultButton = ContentDialogButton.Primary;\n dialog.Content = new ContentDialogContent();\n\n var result = await dialog.ShowAsync();\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BasicContentDialogContent.txt",
+ "source": "WinUIGallery/Samples/ContentDialog/BasicContentDialogContent.txt",
+ "name": "Basic Content Dialog Content"
+ }
+ },
+ {
+ "header": "A content dialog without a default button.",
+ "xaml": "\u003CPage\n x:Class=\u0022WinUIGallery.ControlPages.ContentDialogContent\u0022\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:x=\u0022http://schemas.microsoft.com/winfx/2006/xaml\u0022\u003E\n\n \u003CStackPanel VerticalAlignment=\u0022Stretch\u0022 HorizontalAlignment=\u0022Stretch\u0022\u003E\n \u003C!-- Content body --\u003E\n \u003CTextBlock Text=\u0022Lorem ipsum dolor sit amet, adipisicing elit.\u0022 TextWrapping=\u0022Wrap\u0022 /\u003E\n \u003CCheckBox Content=\u0022Upload your content to the cloud.\u0022/\u003E\n \u003C/StackPanel\u003E\n\n\u003C/Page\u003E",
+ "code": "private async void ShowDialogNoDefault_Click(object sender, RoutedEventArgs e)\n{\n ContentDialog dialog = new ContentDialog();\n\n // XamlRoot must be set in the case of a ContentDialog running in a Desktop app\n dialog.XamlRoot = this.XamlRoot;\n dialog.Title = \u0022Replace file?\u0022;\n dialog.PrimaryButtonText = \u0022Replace\u0022;\n dialog.SecondaryButtonText = \u0022Keep\u0022;\n dialog.CloseButtonText = \u0022Cancel\u0022;\n dialog.DefaultButton = ContentDialogButton.None;\n dialog.Content = new ContentDialogContent();\n\n var result = await dialog.ShowAsync();\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ContentDialogWithoutDefault.txt",
+ "source": "WinUIGallery/Samples/ContentDialog/ContentDialogWithoutDefault.txt",
+ "name": "Without Default"
+ }
+ }
+ ]
+ },
+ {
+ "id": "contentisland",
+ "name": "ContentIsland",
+ "description": "Create ContentIslands to host other frameworks in your app.",
+ "details": "Create ContentIslands to host other frameworks in your app.",
+ "apiNamespace": "Microsoft.UI.Content",
+ "curatedKeywords": [
+ "content island",
+ "hosting",
+ "interop"
+ ],
+ "docs": [
+ {
+ "title": "ContentIsland - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.content.contentisland"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ContentIsland",
+ "group": {
+ "id": "System",
+ "title": "System"
+ },
+ "page": "WinUIGallery/Samples/ContentIsland/ContentIslandPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ContentIsland/ContentIslandPage.xaml.cs",
+ "badges": [
+ "New"
+ ]
+ },
+ "samples": []
+ },
+ {
+ "id": "customusercontrols",
+ "name": "Custom \u0026 User Controls",
+ "description": "Create reusable UI components with custom functionality and appearance.",
+ "details": "Custom controls and user controls allow to create reusable UI components with unique behavior and styling. A UserControl is a simple way to encapsulate a UI layout, while a custom control provides full styling and templating flexibility. Both approaches help in building modular and maintainable applications.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Templates",
+ "Style"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "UserControl",
+ "custom control",
+ "reusable control"
+ ],
+ "docs": [
+ {
+ "title": "Build XAML controls",
+ "uri": "https://learn.microsoft.com/windows/apps/winui/winui3/xaml-templated-controls-csharp-winui-3"
+ },
+ {
+ "title": "Control - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.control"
+ },
+ {
+ "title": "UserControl - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.usercontrol"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CustomUserControls",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/CustomUserControls/CustomUserControlsPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CustomUserControls/CustomUserControlsPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "FrameworkElement",
+ "Control"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Templates",
+ "microsoft/WinUI-Gallery#XamlStyles"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Counter Control with Increment/Decrement Mode",
+ "code": "using Microsoft.UI.Xaml;\nusing Microsoft.UI.Xaml.Controls;\n\nnamespace YourNamespace;\n\n// Enum defining the counter mode: Increment or Decrement\npublic enum CounterMode\n{\n Increment,\n Decrement\n}\n\n// Custom control class that extends Control\npublic sealed class CounterControl : Control\n{\n // DependencyProperty for storing the count value\n public static readonly DependencyProperty CountProperty =\n DependencyProperty.Register(nameof(Count), typeof(int), typeof(CounterControl), new PropertyMetadata(0));\n\n // DependencyProperty for determining the counter mode (Increment or Decrement)\n public static readonly DependencyProperty ModeProperty =\n DependencyProperty.Register(nameof(Mode), typeof(CounterMode), typeof(CounterControl), new PropertyMetadata(CounterMode.Increment));\n\n // Constructor setting the default style key\n public CounterControl()\n {\n this.DefaultStyleKey = typeof(CounterControl);\n }\n\n // Property to get and set the count value\n public int Count\n {\n get =\u003E (int)GetValue(CountProperty);\n set =\u003E SetValue(CountProperty, value);\n }\n\n // Property to get and set the counter mode\n public CounterMode Mode\n {\n get =\u003E (CounterMode)GetValue(ModeProperty);\n set =\u003E SetValue(ModeProperty, value);\n }\n\n // Fields for UI elements retrieved from the control template\n private Button? ActionButton;\n private TextBlock? CountText;\n\n // Method executed when the control\u0027s template is applied\n protected override void OnApplyTemplate()\n {\n base.OnApplyTemplate();\n\n // Retrieve template elements\n ActionButton = GetTemplateChild(nameof(ActionButton)) as Button;\n CountText = GetTemplateChild(nameof(CountText)) as TextBlock;\n\n // Attach event handler to button if it exists\n if (ActionButton is not null)\n {\n ActionButton.Click \u002B= (sender, e) =\u003E\n {\n Count = Mode == CounterMode.Increment ? Count \u002B 1 : Count - 1;\n UpdateUI();\n };\n\n UpdateButtonText();\n }\n\n UpdateUI();\n }\n\n private void UpdateUI()\n {\n if (CountText is not null)\n {\n CountText.Text = Count.ToString();\n }\n }\n\n private void UpdateButtonText()\n {\n if (ActionButton is not null)\n {\n ActionButton.Content = Mode == CounterMode.Increment ? \u0022Increase\u0022 : \u0022Decrease\u0022;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomUserControlsCounterControlIncrementDecrement.txt",
+ "source": "WinUIGallery/Samples/CustomUserControls/CustomUserControlsCounterControlIncrementDecrement.txt",
+ "name": "Counter Control Increment Decrement",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "Basic Custom Password Box with Validation",
+ "code": "using Microsoft.UI.Xaml;\nusing Microsoft.UI.Xaml.Automation.Peers;\nusing Microsoft.UI.Xaml.Controls;\nusing Microsoft.UI.Xaml.Documents;\nusing Microsoft.UI.Xaml.Media;\nusing System.Linq;\nusing Windows.UI;\n\nnamespace YourNamespace;\n\n// Custom control for a validated password box\npublic sealed partial class ValidatedPasswordBox : Control\n{\n // Register a dependency property for the Password value.\n // Note: The PropertyMetadata includes a callback (OnPasswordChanged) so that the UI updates\n // whenever the password or related properties change.\n public static readonly DependencyProperty PasswordProperty =\n DependencyProperty.Register(nameof(Password), typeof(string), typeof(ValidatedPasswordBox), new PropertyMetadata(string.Empty, OnPasswordChanged));\n\n public static readonly DependencyProperty IsValidProperty =\n DependencyProperty.Register(nameof(IsValid), typeof(bool), typeof(ValidatedPasswordBox), new PropertyMetadata(false));\n\n public static readonly DependencyProperty MinLengthProperty =\n DependencyProperty.Register(nameof(MinLength), typeof(int), typeof(ValidatedPasswordBox), new PropertyMetadata(8, OnPasswordChanged));\n\n public static readonly DependencyProperty HeaderProperty =\n DependencyProperty.Register(nameof(Header), typeof(string), typeof(ValidatedPasswordBox), new PropertyMetadata(string.Empty, OnPasswordChanged));\n\n public static readonly DependencyProperty PlaceholderTextProperty =\n DependencyProperty.Register(nameof(PlaceholderText), typeof(string), typeof(ValidatedPasswordBox), new PropertyMetadata(string.Empty, OnPasswordChanged));\n\n public ValidatedPasswordBox()\n {\n this.DefaultStyleKey = typeof(ValidatedPasswordBox);\n }\n\n // CLR property wrappers\n public string Password { get =\u003E (string)GetValue(PasswordProperty); set =\u003E SetValue(PasswordProperty, value); }\n public bool IsValid { get =\u003E (bool)GetValue(IsValidProperty); set =\u003E SetValue(IsValidProperty, value); }\n public int MinLength { get =\u003E (int)GetValue(MinLengthProperty); set =\u003E SetValue(MinLengthProperty, value); }\n public string Header { get =\u003E (string)GetValue(HeaderProperty); set =\u003E SetValue(HeaderProperty, value); }\n public string PlaceholderText { get =\u003E (string)GetValue(PlaceholderTextProperty); set =\u003E SetValue(PlaceholderTextProperty, value); }\n\n // Template parts for password input and validation messages\n private PasswordBox? PasswordInput { get; set; }\n private RichTextBlock? ValidationRichText { get; set; }\n\n protected override void OnApplyTemplate()\n {\n base.OnApplyTemplate();\n\n PasswordInput = GetTemplateChild(nameof(PasswordInput)) as PasswordBox;\n ValidationRichText = GetTemplateChild(\u0022ValidationRichText\u0022) as RichTextBlock;\n\n if (PasswordInput != null)\n {\n PasswordInput.Header = Header;\n PasswordInput.PlaceholderText = PlaceholderText;\n PasswordInput.PasswordChanged \u002B= (_, _) =\u003E Password = PasswordInput.Password;\n }\n\n if (ValidationRichText != null)\n ValidationRichText.ActualThemeChanged \u002B= (_, _) =\u003E UpdateValidationMessages();\n\n UpdateValidationMessages();\n }\n\n private static void OnPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)\n {\n ((ValidatedPasswordBox)d).UpdateValidationMessages();\n }\n\n // Update UI elements based on current password validation\n private void UpdateValidationMessages()\n {\n bool hasMinLength = Password.Length \u003E= MinLength;\n bool hasUppercase = Password.Any(char.IsUpper);\n bool hasNumber = Password.Any(char.IsDigit);\n\n IsValid = hasMinLength \u0026\u0026 hasUppercase \u0026\u0026 hasNumber;\n\n if (ValidationRichText is null)\n return;\n\n ValidationRichText.Visibility = string.IsNullOrEmpty(Password) ? Visibility.Collapsed : Visibility.Visible;\n\n ValidationRichText.Blocks.Clear();\n\n if (string.IsNullOrEmpty(Password))\n return;\n\n var paragraph = new Paragraph();\n\n if (IsValid)\n {\n AddValidationLine(paragraph, \u0022\\uE930\u0022, \u0022Password is valid\u0022, false);\n }\n else\n {\n if (!hasUppercase) AddValidationLine(paragraph, \u0022\\uEA39\u0022, \u0022Missing uppercase\u0022, true);\n if (!hasNumber) AddValidationLine(paragraph, \u0022\\uEA39\u0022, \u0022Missing number\u0022, true);\n if (!hasMinLength) AddValidationLine(paragraph, \u0022\\uEA39\u0022, \u0022Too short!\u0022, true);\n }\n\n if (paragraph.Inlines.Count \u003E 0)\n {\n ValidationRichText.Blocks.Add(paragraph);\n (FrameworkElementAutomationPeer.FromElement(ValidationRichText)\n ?? FrameworkElementAutomationPeer.CreatePeerForElement(ValidationRichText))\n .RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);\n }\n }\n\n private void AddValidationLine(Paragraph paragraph, string iconGlyph, string message, bool isCritical)\n {\n if (paragraph.Inlines.Any())\n paragraph.Inlines.Add(new LineBreak());\n\n var color = new SolidColorBrush(\n isCritical\n ? (ActualTheme == ElementTheme.Light ? Color.FromArgb(255, 196, 43, 28) : Color.FromArgb(255, 255, 153, 164))\n : (ActualTheme == ElementTheme.Light ? Color.FromArgb(255, 15, 123, 15) : Color.FromArgb(255, 108, 203, 95)));\n\n paragraph.Inlines.Add(new InlineUIContainer\n {\n Child = new FontIcon { Glyph = iconGlyph, FontSize = 14, Foreground = color }\n });\n\n paragraph.Inlines.Add(new Run { Text = \u0022 \u0022, });\n paragraph.Inlines.Add(new Run { Text = message, Foreground = color });\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomUserControlsBasicCustomPasswordBox.txt",
+ "source": "WinUIGallery/Samples/CustomUserControls/CustomUserControlsBasicCustomPasswordBox.txt",
+ "name": "Basic Custom Password Box",
+ "xamlOmittedAsMalformed": true
+ }
+ },
+ {
+ "header": "Temperature Converter UserControl example",
+ "code": "using Microsoft.UI.Xaml;\nusing Microsoft.UI.Xaml.Controls;\n\nnamespace YourNamesapace;\n\npublic sealed partial class TemperatureConverterControl : UserControl\n{\n public TemperatureConverterControl()\n {\n this.InitializeComponent();\n }\n\n private void Button_Click(object sender, RoutedEventArgs e)\n {\n string input = InputTextBox.Text;\n double celsius = 0;\n\n bool isNumber = double.TryParse(input, out celsius);\n\n if (isNumber)\n {\n double fahrenheit = (celsius * 9 / 5) \u002B 32;\n ResultTextBlock.Text = \u0022Fahrenheit: \u0022 \u002B fahrenheit.ToString(\u0022F2\u0022) \u002B \u0022\u00B0F\u0022;\n }\n else\n {\n ResultTextBlock.Text = \u0022Invalid input!\u0022;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomUserControlsTemperatureConverterUsercontrolExample.txt",
+ "source": "WinUIGallery/Samples/CustomUserControls/CustomUserControlsTemperatureConverterUsercontrolExample.txt",
+ "name": "Temperature Converter Usercontrol Example",
+ "xamlOmittedAsMalformed": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "customxamlconditionals",
+ "name": "XAML Conditions",
+ "description": "Define custom XAML conditions evaluated at parse time using IXamlCondition.",
+ "details": "XAML conditions let you conditionally include markup based on application-specific state such as feature flags, device capabilities, or configuration. Implement IXamlCondition (Windows App SDK 2.0) and reference your condition from a conditional XAML namespace. Conditions are evaluated by the XAML parser when a page is loaded and the result for each (condition, argument) pair is cached for the lifetime of the process.",
+ "apiNamespace": "Microsoft.UI.Xaml.Markup",
+ "xmlnsImports": [
+ "xmlns:legacy=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(LegacyMode)\u0022",
+ "xmlns:newExp=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(NewExperience)\u0022"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "curatedKeywords": [
+ "IXamlCondition",
+ "conditional XAML",
+ "markup extension"
+ ],
+ "docs": [
+ {
+ "title": "IXamlCondition - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.markup.ixamlcondition"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "CustomXamlConditionals",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/CustomXamlConditionals/CustomXamlConditionalsPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/CustomXamlConditionals/CustomXamlConditionalsPage.xaml.cs",
+ "badges": [
+ "New"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Conditional elements",
+ "xaml": "\u003CPage\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:x=\u0022http://schemas.microsoft.com/winfx/2006/xaml\u0022\n xmlns:cond=\u0022using:WinUIGallery.ControlPages\u0022\n xmlns:newExp=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(NewExperience)\u0022\n xmlns:legacy=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(LegacyMode)\u0022\u003E\n\n \u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003C!-- Included only when FeatureFlagCondition.Evaluate(\u0022NewExperience\u0022) returns true. --\u003E\n \u003CnewExp:InfoBar Title=\u0022New experience\u0022 IsOpen=\u0022True\u0022 Severity=\u0022Success\u0022\n Message=\u0022This InfoBar is included because the \u0027NewExperience\u0027 flag is true.\u0022 /\u003E\n\n \u003C!-- Included only when FeatureFlagCondition.Evaluate(\u0022LegacyMode\u0022) returns true. --\u003E\n \u003Clegacy:InfoBar Title=\u0022Legacy mode\u0022 IsOpen=\u0022True\u0022 Severity=\u0022Warning\u0022\n Message=\u0022This InfoBar is included because the \u0027LegacyMode\u0027 flag is true.\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/Page\u003E",
+ "code": "// Set the active feature flag(s) BEFORE InitializeComponent so the\n// XAML parser sees them when it evaluates the conditional elements.\n// In a real app these are typically set once at startup (e.g. from\n// App.OnLaunched) based on configuration, A/B test assignment, or\n// device capability detection. Once parsed, the result for each\n// (condition, argument) pair is cached for the lifetime of the\n// process - changing a flag later does NOT re-render markup that\n// was already parsed.\npublic sealed partial class MyPage : Page\n{\n public MyPage()\n {\n FeatureFlagCondition.FeatureFlags[\u0022NewExperience\u0022] = true;\n FeatureFlagCondition.FeatureFlags[\u0022LegacyMode\u0022] = false;\n\n this.InitializeComponent();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomXamlConditionalsConditionalElements.txt",
+ "source": "WinUIGallery/Samples/CustomXamlConditionals/CustomXamlConditionalsConditionalElements.txt",
+ "name": "Conditional Elements"
+ }
+ },
+ {
+ "header": "Conditional attributes",
+ "xaml": "\u003CPage\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:cond=\u0022using:WinUIGallery.ControlPages\u0022\n xmlns:newExp=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(NewExperience)\u0022\n xmlns:legacy=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(LegacyMode)\u0022\u003E\n\n \u003C!--\n At most ONE of newExp:Background and legacy:Background may evaluate to true at a time.\n If both conditions are true, the XAML parser throws at runtime.\n --\u003E\n \u003CButton Content=\u0022Background depends on the active flag\u0022\n newExp:Background=\u0022Green\u0022\n legacy:Background=\u0022Gray\u0022\n Foreground=\u0022White\u0022 /\u003E\n\u003C/Page\u003E",
+ "code": "// Conditional attributes use the same setup. Make sure that, for any\n// given attribute, no more than one condition can evaluate to true at\n// the same time - if multiple are true the XAML parser will throw at\n// runtime.\npublic sealed partial class MyPage : Page\n{\n public MyPage()\n {\n FeatureFlagCondition.FeatureFlags[\u0022NewExperience\u0022] = true;\n FeatureFlagCondition.FeatureFlags[\u0022LegacyMode\u0022] = false;\n\n this.InitializeComponent();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomXamlConditionalsConditionalAttributes.txt",
+ "source": "WinUIGallery/Samples/CustomXamlConditionals/CustomXamlConditionalsConditionalAttributes.txt",
+ "name": "Conditional Attributes"
+ }
+ },
+ {
+ "header": "Conditional Setters in a Style",
+ "xaml": "\u003CPage\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:cond=\u0022using:WinUIGallery.ControlPages\u0022\n xmlns:newExp=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(NewExperience)\u0022\n xmlns:legacy=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation?cond:FeatureFlagCondition(LegacyMode)\u0022\u003E\n\n \u003CPage.Resources\u003E\n \u003CStyle x:Key=\u0022ConditionalHeadingStyle\u0022 TargetType=\u0022TextBlock\u0022\u003E\n \u003C!-- Setters can also be qualified with a conditional namespace. --\u003E\n \u003CnewExp:Setter Property=\u0022FontWeight\u0022 Value=\u0022SemiBold\u0022 /\u003E\n \u003CnewExp:Setter Property=\u0022FontSize\u0022 Value=\u002228\u0022 /\u003E\n \u003Clegacy:Setter Property=\u0022FontWeight\u0022 Value=\u0022Normal\u0022 /\u003E\n \u003Clegacy:Setter Property=\u0022FontSize\u0022 Value=\u002218\u0022 /\u003E\n \u003C/Style\u003E\n \u003C/Page.Resources\u003E\n\n \u003CTextBlock Text=\u0022Heading styled with conditional Setters\u0022\n Style=\u0022{StaticResource ConditionalHeadingStyle}\u0022 /\u003E\n\u003C/Page\u003E",
+ "code": "// Conditional Setters inside a Style are evaluated when the Style\n// resource is first parsed. Set the flags before InitializeComponent\n// (or before the resource dictionary that contains the Style is\n// loaded) so the parser produces the Style you expect.\npublic sealed partial class MyPage : Page\n{\n public MyPage()\n {\n FeatureFlagCondition.FeatureFlags[\u0022NewExperience\u0022] = true;\n FeatureFlagCondition.FeatureFlags[\u0022LegacyMode\u0022] = false;\n\n this.InitializeComponent();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomXamlConditionalsConditionalSettersStyle.txt",
+ "source": "WinUIGallery/Samples/CustomXamlConditionals/CustomXamlConditionalsConditionalSettersStyle.txt",
+ "name": "Conditional Setters Style"
+ }
+ }
+ ]
+ },
+ {
+ "id": "datepicker",
+ "name": "DatePicker",
+ "description": "A control that lets a user pick a date value.",
+ "details": "Use a DatePicker to let users set a date in your app, for example to schedule an appointment. The DatePicker displays three controls for month, date, and year. These controls are easy to use with touch or mouse, and they can be styled and configured in several different ways.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "CalendarDatePicker",
+ "CalendarView",
+ "TimePicker"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "date selection"
+ ],
+ "docs": [
+ {
+ "title": "DatePicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.datepicker"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/date-picker"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "DatePicker",
+ "group": {
+ "id": "DateAndTime",
+ "title": "Date \u0026 time"
+ },
+ "page": "WinUIGallery/Samples/DatePicker/DatePickerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/DatePicker/DatePickerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CalendarDatePicker",
+ "microsoft/WinUI-Gallery#CalendarView",
+ "microsoft/WinUI-Gallery#TimePicker"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple DatePicker with a header.",
+ "xaml": "\u003CDatePicker Header=\u0022Pick a date\u0022 /\u003E",
+ "gallery": {
+ "snippet": "SimpleDatepickerHeader.txt",
+ "source": "WinUIGallery/Samples/DatePicker/SimpleDatepickerHeader.txt",
+ "name": "Simple Datepicker Header"
+ }
+ },
+ {
+ "header": "A DatePicker with day formatted and year hidden.",
+ "xaml": "\u003CDatePicker DayFormat=\u0022{}{day.integer} ({dayofweek.abbreviated})\u0022 YearVisible=\u0022False\u0022 /\u003E",
+ "gallery": {
+ "snippet": "DatepickerDayFormattedYear.txt",
+ "source": "WinUIGallery/Samples/DatePicker/DatepickerDayFormattedYear.txt",
+ "name": "Day Formatted Year"
+ }
+ }
+ ]
+ },
+ {
+ "id": "dropdownbutton",
+ "name": "DropDownButton",
+ "description": "A button that displays a flyout of choices when clicked.",
+ "details": "A control that drops down a flyout of choices from which one can be chosen.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "SplitButton",
+ "ToggleSplitButton",
+ "ToggleButton",
+ "RepeatButton",
+ "HyperlinkButton",
+ "AppBarButton",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "Button"
+ ],
+ "curatedKeywords": [
+ "flyout button",
+ "menu button"
+ ],
+ "docs": [
+ {
+ "title": "DropDownButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.dropdownbutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "DropDownButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/DropDownButton/DropDownButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/DropDownButton/DropDownButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "Button"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#HyperlinkButton",
+ "microsoft/WinUI-Gallery#RepeatButton",
+ "microsoft/WinUI-Gallery#SplitButton",
+ "microsoft/WinUI-Gallery#ToggleButton",
+ "microsoft/WinUI-Gallery#ToggleSplitButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Simple DropDownButton",
+ "xaml": "\u003CDropDownButton Content=\u0022Email\u0022\u003E\n \u003CDropDownButton.Flyout\u003E\n \u003CMenuFlyout Placement=\u0022Bottom\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Send\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Reply\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Reply All\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/DropDownButton.Flyout\u003E\n\u003C/DropDownButton\u003E",
+ "gallery": {
+ "snippet": "DropDownButtonSimple.txt",
+ "source": "WinUIGallery/Samples/DropDownButton/DropDownButtonSimple.txt",
+ "name": "Simple"
+ }
+ },
+ {
+ "header": "DropDownButton with Icons",
+ "xaml": "\u003CDropDownButton AutomationProperties.Name=\u0022Email\u0022\u003E\n \u003CDropDownButton.Content\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE715;\u0022/\u003E\n \u003C/DropDownButton.Content\u003E\n \u003CDropDownButton.Flyout\u003E\n \u003CMenuFlyout Placement=\u0022Bottom\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Send\u0022\u003E\n \u003CMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE725;\u0022/\u003E\n \u003C/MenuFlyoutItem.Icon\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Reply\u0022\u003E\n \u003CMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE8CA;\u0022/\u003E\n \u003C/MenuFlyoutItem.Icon\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Reply All\u0022\u003E\n \u003CMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE8C2;\u0022/\u003E\n \u003C/MenuFlyoutItem.Icon\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003C/MenuFlyout\u003E\n \u003C/DropDownButton.Flyout\u003E\n\u003C/DropDownButton\u003E",
+ "gallery": {
+ "snippet": "DropDownButtonIcon.txt",
+ "source": "WinUIGallery/Samples/DropDownButton/DropDownButtonIcon.txt",
+ "name": "Icon"
+ }
+ }
+ ]
+ },
+ {
+ "id": "easingfunction",
+ "name": "Easing Functions",
+ "description": "Easing is a way to manipulate the velocity of an object as it animates.",
+ "details": "Easing is a way to manipulate the velocity of an object as it animates.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media.Animation",
+ "relatedControls": [
+ "Connected Animation",
+ "Page Transitions",
+ "Theme Transitions"
+ ],
+ "curatedKeywords": [
+ "animation curve",
+ "velocity"
+ ],
+ "docs": [
+ {
+ "title": "EasingFunctionBase - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.animation.easingfunctionbase"
+ },
+ {
+ "title": "Timing and Easing",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/timing-and-easing"
+ },
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "EasingFunction",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/EasingFunction/EasingFunctionPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/EasingFunction/EasingFunctionPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ConnectedAnimation",
+ "microsoft/WinUI-Gallery#PageTransition",
+ "microsoft/WinUI-Gallery#ThemeTransition"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Standard Easing Function",
+ "xaml": "\u003CStoryboard x:Name=\u0022Storyboard1\u0022\u003E\n \u003CDoubleAnimation Storyboard.TargetName=\u0022Translation\u0022 Storyboard.TargetProperty=\u0022X\u0022 From=\u00220\u0022 To=\u0022200\u0022 \u003E\n \u003CDoubleAnimation.EasingFunction\u003E\n \u003CCircleEase EasingMode=\u0022EaseInOut\u0022 /\u003E\n \u003C/DoubleAnimation.EasingFunction\u003E\n \u003C/DoubleAnimation\u003E\n\u003C/Storyboard\u003E",
+ "gallery": {
+ "snippet": "StandardEasingFunction.txt",
+ "source": "WinUIGallery/Samples/EasingFunction/StandardEasingFunction.txt",
+ "name": "Standard Easing Function"
+ }
+ },
+ {
+ "header": "Accelerate Easing Function",
+ "xaml": "\u003CStoryboard x:Name=\u0022Storyboard2\u0022\u003E\n \u003CDoubleAnimation Storyboard.TargetName=\u0022Translation\u0022 Storyboard.TargetProperty=\u0022X\u0022 From=\u00220\u0022 To=\u0022200\u0022 \u003E\n \u003CDoubleAnimation.EasingFunction\u003E\n \u003CExponentialEase Exponent=\u00224.5\u0022 EasingMode=\u0022EaseIn\u0022 /\u003E\n \u003C/DoubleAnimation.EasingFunction\u003E\n \u003C/DoubleAnimation\u003E\n\u003C/Storyboard\u003E",
+ "gallery": {
+ "snippet": "AccelerateEasingFunction.txt",
+ "source": "WinUIGallery/Samples/EasingFunction/AccelerateEasingFunction.txt",
+ "name": "Accelerate Easing Function"
+ }
+ },
+ {
+ "header": "Decelerate Easing Function",
+ "xaml": "\u003CStoryboard x:Name=\u0022Storyboard3\u0022\u003E\n \u003CDoubleAnimation Storyboard.TargetName=\u0022Translation\u0022 Storyboard.TargetProperty=\u0022X\u0022 From=\u00220\u0022 To=\u0022200\u0022 \u003E\n \u003CDoubleAnimation.EasingFunction\u003E\n \u003CExponentialEase Exponent=\u00227\u0022 EasingMode=\u0022EaseOut\u0022 /\u003E\n \u003C/DoubleAnimation.EasingFunction\u003E\n \u003C/DoubleAnimation\u003E\n\u003C/Storyboard\u003E",
+ "gallery": {
+ "snippet": "DecelerateEasingFunction.txt",
+ "source": "WinUIGallery/Samples/EasingFunction/DecelerateEasingFunction.txt",
+ "name": "Decelerate Easing Function"
+ }
+ }
+ ]
+ },
+ {
+ "id": "expander",
+ "name": "Expander",
+ "description": "A container with a header that can be expanded to show a body with more content.",
+ "details": "The Expander has a header and can expand to show a body with more content. Use an Expander when some content is only relevant some of the time (for example to read more information or access additional options for an item).",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Flyout",
+ "ItemsRepeater",
+ "SplitView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "collapse",
+ "accordion"
+ ],
+ "docs": [
+ {
+ "title": "Expander - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.expander"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/expander"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Expander",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/Expander/ExpanderPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Expander/ExpanderPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Flyout",
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#SplitView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An Expander with text in the header and content areas",
+ "xaml": "\u003CExpander\n IsExpanded=\u0022False\u0022\n VerticalAlignment=\u0022Top\u0022\n Header=\u0022This text is in the header\u0022\n Content=\u0022This is in the content\u0022/\u003E",
+ "gallery": {
+ "snippet": "ExpanderTextHeaderContent.txt",
+ "source": "WinUIGallery/Samples/Expander/ExpanderTextHeaderContent.txt",
+ "name": "Text Header Content",
+ "xamlPlaceholdersDropped": [
+ "ExpandDirection"
+ ]
+ }
+ },
+ {
+ "header": "Modifying Expanders content alignment",
+ "xaml": "\u003CExpander Width=\u0022500\u0022 HorizontalContentAlignment=\u0022Left\u0022 Padding=\u00220\u0022\u003E\n \u003CExpander.Header\u003E\n \u003CToggleButton Content=\u0022This ToggleButton is centered\u0022 HorizontalAlignment=\u0022Center\u0022/\u003E\n \u003C/Expander.Header\u003E\n \u003CExpander.Content\u003E\n \u003CButton Margin=\u00224\u0022 Content=\u0022This Button is left aligned\u0022/\u003E\n \u003C/Expander.Content\u003E\n\u003C/Expander\u003E",
+ "gallery": {
+ "snippet": "ModifyingExpandersContentAlignment.txt",
+ "source": "WinUIGallery/Samples/Expander/ModifyingExpandersContentAlignment.txt",
+ "name": "Modifying Expanders Content Alignment"
+ }
+ }
+ ]
+ },
+ {
+ "id": "flipview",
+ "name": "FlipView",
+ "description": "Presents a collection of items that the user can flip through, one item at a time.",
+ "details": "The FlipView lets you flip through a collection of items, one at a time. It\u0027s great for displaying images from a gallery, pages of a magazine, or similar items.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "GridView",
+ "ListView",
+ "SemanticZoom"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector"
+ ],
+ "curatedKeywords": [
+ "carousel",
+ "slideshow",
+ "gallery"
+ ],
+ "docs": [
+ {
+ "title": "FlipView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.flipview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/flipview"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "FlipView",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/FlipView/FlipViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/FlipView/FlipViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#SemanticZoom"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple FlipView with items declared inline.",
+ "xaml": "\u003CFlipView MaxWidth=\u0022400\u0022 Height=\u0022270\u0022\n AutomationProperties.AutomationControlType=\u0022List\u0022\n AutomationProperties.LocalizedControlType=\u0022list\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 AutomationProperties.Name=\u0022Cliff\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/grapes.jpg\u0022 AutomationProperties.Name=\u0022Grapes\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/rainier.jpg\u0022 AutomationProperties.Name=\u0022Rainier\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/sunset.jpg\u0022 AutomationProperties.Name=\u0022Sunset\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/valley.jpg\u0022 AutomationProperties.Name=\u0022Valley\u0022/\u003E\n\u003C/FlipView\u003E",
+ "gallery": {
+ "snippet": "SimpleFlipviewItemsDeclared.txt",
+ "source": "WinUIGallery/Samples/FlipView/SimpleFlipviewItemsDeclared.txt",
+ "name": "Simple Flipview Items Declared"
+ }
+ },
+ {
+ "header": "Vertical FlipView",
+ "xaml": "\u003CFlipView MaxWidth=\u0022400\u0022 Height=\u0022270\u0022\n AutomationProperties.AutomationControlType=\u0022List\u0022\n AutomationProperties.LocalizedControlType=\u0022list\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 AutomationProperties.Name=\u0022Cliff\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/grapes.jpg\u0022 AutomationProperties.Name=\u0022Grapes\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/rainier.jpg\u0022 AutomationProperties.Name=\u0022Rainier\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/sunset.jpg\u0022 AutomationProperties.Name=\u0022Sunset\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/valley.jpg\u0022 AutomationProperties.Name=\u0022Valley\u0022/\u003E\n \u003CFlipView.ItemsPanel \u003E\n \u003CItemsPanelTemplate\u003E\n \u003CVirtualizingStackPanel Orientation=\u0022Vertical\u0022/\u003E\n \u003C/ItemsPanelTemplate\u003E\n \u003C/FlipView.ItemsPanel\u003E\n\u003C/FlipView\u003E",
+ "gallery": {
+ "snippet": "VerticalFlipview.txt",
+ "source": "WinUIGallery/Samples/FlipView/VerticalFlipview.txt",
+ "name": "Vertical Flipview"
+ }
+ }
+ ]
+ },
+ {
+ "id": "flyout",
+ "name": "Flyout",
+ "description": "Shows contextual information and enables user interaction.",
+ "details": "A Flyout displays lightweight UI that is either information, or requires user interaction. Unlike a dialog, a Flyout can be light dismissed by clicking or tapping off of it. Use it to collect input from the user, show more details about an item, or ask the user to confirm an action.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "TeachingTip",
+ "ContentDialog",
+ "MenuFlyout",
+ "Button",
+ "AppBarButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "curatedKeywords": [
+ "popup",
+ "contextual"
+ ],
+ "docs": [
+ {
+ "title": "Flyout - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.flyout"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/dialogs-and-flyouts"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Flyout",
+ "group": {
+ "id": "DialogsAndFlyouts",
+ "title": "Dialogs \u0026 flyouts"
+ },
+ "page": "WinUIGallery/Samples/Flyout/FlyoutPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Flyout/FlyoutPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#ContentDialog",
+ "microsoft/WinUI-Gallery#MenuFlyout",
+ "microsoft/WinUI-Gallery#TeachingTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A button with a flyout",
+ "xaml": "\u003CButton Content=\u0022Empty cart\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CFlyout\u003E\n \u003CStackPanel\u003E\n \u003CTextBlock Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022 Text=\u0022All items will be removed. Do you want to continue?\u0022 Margin=\u00220,0,0,12\u0022 /\u003E\n \u003CButton Click=\u0022DeleteConfirmation_Click\u0022 Content=\u0022Yes, empty my cart\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/Flyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "ButtonFlyout.txt",
+ "source": "WinUIGallery/Samples/Flyout/ButtonFlyout.txt",
+ "name": "Button Flyout"
+ }
+ }
+ ]
+ },
+ {
+ "id": "geometry",
+ "name": "Geometry",
+ "description": "Clear geometric design ensures visual coherence and structure.",
+ "curatedKeywords": [
+ "path",
+ "vector",
+ "figures"
+ ],
+ "docs": [
+ {
+ "title": "Geometry in Windows 11",
+ "uri": "https://learn.microsoft.com/windows/apps/design/signature-experiences/geometry"
+ },
+ {
+ "title": "WinUI Theme Resources (GitHub)",
+ "uri": "https://github.com/microsoft/microsoft-ui-xaml/blob/main/controls/dev/CommonStyles/Common_themeresources_any.xaml"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Geometry",
+ "group": {
+ "id": "DesignItem",
+ "title": "Design"
+ },
+ "page": "WinUIGallery/Samples/Geometry/GeometryPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Geometry/GeometryPage.xaml.cs"
+ },
+ "samples": [
+ {
+ "header": "Geometry",
+ "xaml": "\u003CGrid CornerRadius=\u0022{StaticResource OverlayCornerRadius}\u0022/\u003E\n\u003CGrid CornerRadius=\u0022{StaticResource ControlCornerRadius}\u0022/\u003E",
+ "gallery": {
+ "snippet": "Geometry.txt",
+ "source": "WinUIGallery/Samples/Geometry/Geometry.txt",
+ "name": "Geometry"
+ }
+ }
+ ]
+ },
+ {
+ "id": "grid",
+ "name": "Grid",
+ "description": "A layout panel that supports arranging child elements in rows and columns. ",
+ "details": "The Grid is used to arrange controls and content in rows and columns. Content is positioned in the grid using Grid.Row and Grid.Column attached properties.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Border",
+ "Canvas",
+ "StackPanel",
+ "VariableSizedWrapGrid",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "rows",
+ "columns"
+ ],
+ "docs": [
+ {
+ "title": "Grid - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.grid"
+ },
+ {
+ "title": "Tutorial",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/grid-tutorial"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/layout-panels#grid"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Grid",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/Grid/GridPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Grid/GridPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Border",
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#VariableSizedWrapGrid"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A 3x3 Grid control.",
+ "xaml": "\u003CGrid\n Width=\u0022240\u0022\n Height=\u0022120\u0022\n Background=\u0022Gray\u0022\n ColumnDefinitions=\u002250, 50, 50\u0022\n RowDefinitions =\u002250, 50, 50\u0022\n ColumnSpacing=\u00228\u0022\n RowSpacing=\u00228\u0022\u003E\n \u003CRectangle Fill=\u0022Red\u0022 /\u003E\n \u003CRectangle Fill=\u0022Blue\u0022 Grid.Row=\u00221\u0022 /\u003E\n \u003CRectangle Fill=\u0022Green\u0022 Grid.Column=\u00221\u0022 /\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022 Grid.Column=\u00221\u0022 Grid.Row=\u00221\u0022 /\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "3x3GridControl.txt",
+ "source": "WinUIGallery/Samples/Grid/3x3GridControl.txt",
+ "name": "3x3 Grid Control",
+ "xamlPlaceholdersDropped": [
+ "Column",
+ "Row"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "gridview",
+ "name": "GridView",
+ "description": "A control that presents a collection of items in rows and columns.",
+ "details": "The GridView lets you show a collection of items arranged in rows and columns that scroll horizontally.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ItemsView",
+ "ListView",
+ "FlipView",
+ "SemanticZoom"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Navigation",
+ "System.Collections.Generic",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector",
+ "ListViewBase"
+ ],
+ "curatedKeywords": [
+ "tiles",
+ "collection grid"
+ ],
+ "docs": [
+ {
+ "title": "GridView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.gridview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/lists"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "GridView",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/GridView/GridViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/GridView/GridViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector",
+ "ListViewBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#FlipView",
+ "microsoft/WinUI-Gallery#ItemsView",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#SemanticZoom"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic GridView with Simple DataTemplate",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003CGridView\n x:Name=\u0022BasicGridView\u0022\n ItemTemplate=\u0022{StaticResource ImageTemplate}\u0022\n IsItemClickEnabled=\u0022True\u0022\n ItemClick=\u0022BasicGridView_ItemClick\u0022\n SelectionMode=\u0022Single\u0022/\u003E\n \n\u003CDataTemplate x:Key=\u0022ImageTemplate\u0022 x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CImage Stretch=\u0022UniformToFill\u0022 Source=\u0022{x:Bind ImageLocation}\u0022 Width=\u0022190\u0022 Height=\u0022130\u0022/\u003E\n\u003C/DataTemplate\u003E\n \n\u003C!-- In this example, the GridView\u0027s ItemTemplate property is bound to a data template (shown above)\ncalled ImageTemplate, defined in the Page.Resources section of the XAML file. \n \nThe data template is defined to display an object of type CustomDataObject, which is created from a class\nthat\u0027s defined in the code-behind (see code below).\n \nThe ItemsSource for the GridView is an ObservableCollection\u003CCustomDataObject\u003E called Items and\nis defined in the C# code-behind. It is bound to the GridView\u0027s ItemsSource property in the code-behind.\n \nThe IsItemClickEnabled property allows items to be clicked, and a function called BasicGridView_ItemClick \nis called when an item is clicked. This function is defined in the C# code-behind and simply outputs \nthe title of the selected item into a TextBlock below the GridView. --\u003E",
+ "code": "// C# Code\n\n// CustomDataObject class definition: \npublic class CustomDataObject\n{\n public string Title { get; set; } = string.Empty;\n public string ImageLocation { get; set; } = string.Empty;\n public string Views { get; set; } = string.Empty;\n public string Likes { get; set; } = string.Empty;\n public string Description { get; set; } = string.Empty;\n\n public CustomDataObject()\n {\n }\n\n\t\n // ... Methods ...\n}",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "BasicGridviewSimpleDatatemplate.txt",
+ "source": "WinUIGallery/Samples/GridView/BasicGridviewSimpleDatatemplate.txt",
+ "name": "Basic Gridview Simple Datatemplate"
+ }
+ },
+ {
+ "header": "GridView with Layout Customization",
+ "xaml": "\u003C!-- The GridView used for this example is shown below. Setter properties are used to customize \nsome parts of the GridViewItems (i.e. the margins). --\u003E\n\u003CGridView\n x:Name=\u0022StyledGrid\u0022\n ItemTemplate=\u0022{StaticResource ImageOverlayTemplate}\u0022\u003E\n\n \u003CGridView.ItemContainerStyle\u003E\n \u003CStyle TargetType=\u0022GridViewItem\u0022 BasedOn=\u0022{StaticResource DefaultGridViewItemStyle}\u0022\u003E\n \u003CSetter Property=\u0022Margin\u0022 Value=\u00225, 5, 5, 5\u0022/\u003E\n \u003C/Style\u003E\n \u003C/GridView.ItemContainerStyle\u003E\n \n \u003C!-- An extra property also needs to be added to the GridView\u0027s ItemsWrapGrid. \n The following sets the maximum # of items to show before wrapping.--\u003E\n \u003CGridView.ItemsPanel\u003E\n \u003CItemsPanelTemplate\u003E\n \u003CItemsWrapGrid x:Name=\u0022MaxItemsWrapGrid\u0022 \n MaximumRowsOrColumns=\u00223\u0022 \n Orientation=\u0022Horizontal\u0022/\u003E\n \u003C/ItemsPanelTemplate\u003E\n \u003C/GridView.ItemsPanel\u003E \n\u003C/GridView\u003E \n \n\u003C!-- In this example, the GridView\u0027s ItemTemplate property is bound to a data template (shown below)\ncalled ImageOverlayTemplate, defined in the Page.Resources section of the XAML file. \n \nThe data template is defined to display a CustomDataObject object (same type as in above sample). --\u003E\n \n\u003CDataTemplate x:Name=\u0022ImageOverlayTemplate\u0022 x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CGrid Width=\u0022100\u0022\u003E\n \u003CImage Source=\u0022{x:Bind ImageLocation}\u0022 Stretch=\u0022UniformToFill\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Vertical\u0022 Height=\u002240\u0022 VerticalAlignment=\u0022Bottom\u0022 Padding=\u00225,1,5,1\u0022 \n Background=\u0022LightGray\u0022 Opacity=\u0022.75\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Title}\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Likes}\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 \n Foreground=\u0022{ThemeResource SystemControlPageTextBaseMediumBrush}\u0022/\u003E\n \u003CTextBlock Text=\u0022 Likes\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 \n Foreground=\u0022{ThemeResource SystemControlPageTextBaseMediumBrush}\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "GridviewLayoutCustomization.txt",
+ "source": "WinUIGallery/Samples/GridView/GridviewLayoutCustomization.txt",
+ "name": "Layout Customization"
+ }
+ },
+ {
+ "header": "Content inside of a GridView.",
+ "xaml": "\u003C!-- The GridView used for this sample is shown below, with all of the necessary added properties. --\u003E\n\u003CGridView \n x:Name=\u0022ContentGridView\u0022\n ItemsSource=\u0022{x:Bind Items}\u0022\n ItemTemplate=\u0022{StaticResource ImageTemplate}\u0022\n IsItemClickEnabled=\u0022{x:Bind ItemClickCheckBox.IsChecked.Value, Mode=OneWay}\u0022\n CanDragItems=\u0022{x:Bind DragCheckBox.IsChecked.Value, Mode=OneWay}\u0022\n AllowDrop=\u0022{x:Bind DropCheckBox.IsChecked.Value, Mode=OneWay}\u0022\n CanReorderItems=\u0022{x:Bind ReorderCheckBox.IsChecked.Value, Mode=OneWay}\u0022\n SelectionChanged=\u0022ContentGridView_SelectionChanged\u0022\n ItemClick=\u0022ContentGridView_ItemClick\u0022 \n FlowDirection=\u0022LeftToRight\u0022/\u003E\n\n\u003C!-- ContentGridView_SelectionChanged and ContentGridView_ItemClick are functions defined in the code-behind\nto handle the events of when a selection changes on the GridView and when an item is clicked. --\u003E\n \n\u003C!-- The data template bound to this GridView\u0027s ItemTemplate property is based on which one you\nselect from the options on the right. The currently selected DataTemplate is: --\u003E\n",
+ "gallery": {
+ "snippet": "ContentInsideGridview.txt",
+ "source": "WinUIGallery/Samples/GridView/ContentInsideGridview.txt",
+ "name": "Content Inside Gridview",
+ "xamlPlaceholdersDropped": [
+ "SelectionMode",
+ "DisplayDT"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "hyperlinkbutton",
+ "name": "HyperlinkButton",
+ "description": "A button that appears as hyperlink text, and can navigate to a URI or handle a Click event.",
+ "details": "A HyperlinkButton appears as a text hyperlink. When a user clicks it, it opens the page you specify in the NavigateUri property in the default browser. Or you can handle its Click event, typically to navigate within your app.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Button",
+ "ToggleButton",
+ "RepeatButton",
+ "AppBarButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "curatedKeywords": [
+ "URL",
+ "navigate"
+ ],
+ "docs": [
+ {
+ "title": "HyperlinkButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.hyperlinkbutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/hyperlinks"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "HyperlinkButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/HyperlinkButton/HyperlinkButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/HyperlinkButton/HyperlinkButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#RepeatButton",
+ "microsoft/WinUI-Gallery#ToggleButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A hyperlink button that navigates to a URI.",
+ "xaml": "\u003CHyperlinkButton Content=\u0022Microsoft home page\u0022 NavigateUri=\u0022https://www.microsoft.com\u0022 /\u003E",
+ "gallery": {
+ "snippet": "HyperlinkButtonNavigate.txt",
+ "source": "WinUIGallery/Samples/HyperlinkButton/HyperlinkButtonNavigate.txt",
+ "name": "Navigate"
+ }
+ },
+ {
+ "header": "A hyperlink button that handles a Click event.",
+ "xaml": "\u003CHyperlinkButton Content=\u0022ToggleButton\u0022 Click=\u0022HyperlinkButton_Click\u0022/\u003E",
+ "gallery": {
+ "snippet": "HyperlinkButtonClick.txt",
+ "source": "WinUIGallery/Samples/HyperlinkButton/HyperlinkButtonClick.txt",
+ "name": "Click"
+ }
+ }
+ ]
+ },
+ {
+ "id": "iconelement",
+ "name": "IconElement",
+ "description": "Represents icon controls that use different image types as its content.",
+ "details": "Represents icon controls that use different image types as its content.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AnimatedIcon",
+ "AppBarButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "BitmapIcon",
+ "FontIcon",
+ "PathIcon",
+ "SymbolIcon",
+ "ImageIcon",
+ "AnimatedIcon"
+ ],
+ "docs": [
+ {
+ "title": "BitmapIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.bitmapicon"
+ },
+ {
+ "title": "FontIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.fonticon"
+ },
+ {
+ "title": "ImageIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.imageicon"
+ },
+ {
+ "title": "PathIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.pathicon"
+ },
+ {
+ "title": "SymbolIcon - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.symbolicon"
+ },
+ {
+ "title": "Icon Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/icons"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "IconElement",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/IconElement/IconElementPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/IconElement/IconElementPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AnimatedIcon",
+ "microsoft/WinUI-Gallery#AppBarButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A BitmapIcon with a multicolor bitmap image",
+ "xaml": "\u003CBitmapIcon x:Name=\u0022SlicesIcon\u0022 UriSource=\u0022ms-appx:///Assets/SampleMedia/Slices.png\u0022 Width=\u002250\u0022/\u003E",
+ "gallery": {
+ "snippet": "IconElementBitmapiconMulticolorBitmapImage.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementBitmapiconMulticolorBitmapImage.txt",
+ "name": "Bitmapicon Multicolor Bitmap Image",
+ "xamlPlaceholdersDropped": [
+ "ShowAsMonochrome"
+ ]
+ }
+ },
+ {
+ "header": "A FontIcon using a glyph from a specific font family in a button",
+ "xaml": "\u003CButton Name=\u0022ExampleButton1\u0022\u003E\n \u003CFontIcon FontFamily=\u0022Segoe MDL2 Assets\u0022 Glyph=\u0022\u0026#xE790;\u0022/\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "IconElementFonticonGlyphSpecificFont.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementFonticonGlyphSpecificFont.txt",
+ "name": "Fonticon Glyph Specific Font"
+ }
+ },
+ {
+ "header": "A ImageIcon using a bitmap image in a button",
+ "xaml": "\u003CButton Name=\u0022ImageExample1\u0022 Width=\u0022100\u0022\u003E\n \u003CImageIcon Source=\u0022/Assets/SampleMedia/slices.png\u0022/\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "IconElementImageiconBitmapImageButton.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementImageiconBitmapImageButton.txt",
+ "name": "Imageicon Bitmap Image Button"
+ }
+ },
+ {
+ "header": "A ImageIcon using a SVG image in a button",
+ "xaml": "\u003CButton Name=\u0022ImageExample2\u0022\u003E\n \u003CImageIcon Source=\u0022https://raw.githubusercontent.com/DiemenDesign/LibreICONS/master/svg-color/libre-camera-panorama.svg\u0022 Width=\u002250\u0022/\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "IconElementImageiconSvgImageButton.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementImageiconSvgImageButton.txt",
+ "name": "Imageicon Svg Image Button"
+ }
+ },
+ {
+ "header": "A PathIcon in a button",
+ "xaml": "\u003CButton Name=\u0022Example1Button\u0022\u003E\n \u003CPathIcon Data=\u0022F1 M 16,12 20,2L 20,16 1,16\u0022 HorizontalAlignment=\u0022Center\u0022/\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "IconElementPathiconButton.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementPathiconButton.txt",
+ "name": "Pathicon Button"
+ }
+ },
+ {
+ "header": "A SymbolIcon in a button",
+ "xaml": "\u003CButton Name=\u0022AcceptButton\u0022\u003E\n \u003CStackPanel\u003E\n \u003CSymbolIcon Symbol=\u0022Accept\u0022/\u003E\n \u003CTextBlock Text=\u0022Accept\u0022/\u003E\n \u003C/StackPanel\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "IconElementSymboliconButton.txt",
+ "source": "WinUIGallery/Samples/IconElement/IconElementSymboliconButton.txt",
+ "name": "Symbolicon Button"
+ }
+ }
+ ]
+ },
+ {
+ "id": "iconography",
+ "name": "Iconography",
+ "description": "Icons are a visual design language that can be used to communicate information quickly and effectively.",
+ "details": "The icons below use Segoe Fluent Icons on Windows 11 and Segoe MDL2 Assets on Windows 10.",
+ "curatedKeywords": [
+ "icons",
+ "glyph",
+ "Segoe Fluent Icons",
+ "FontIcon",
+ "SymbolIcon",
+ "icon font"
+ ],
+ "docs": [
+ {
+ "title": "Iconography in Windows",
+ "uri": "https://learn.microsoft.com/windows/apps/design/signature-experiences/iconography#system-icons"
+ },
+ {
+ "title": "Segoe Fluent Icons font",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/segoe-fluent-icons-font"
+ },
+ {
+ "title": "Segoe MDL2 Assets font",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/segoe-ui-symbol-font"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Iconography",
+ "group": {
+ "id": "DesignItem",
+ "title": "Design"
+ },
+ "page": "WinUIGallery/Samples/Iconography/IconographyPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Iconography/IconographyPage.xaml.cs",
+ "badges": [
+ "Updated"
+ ]
+ },
+ "samples": []
+ },
+ {
+ "id": "image",
+ "name": "Image",
+ "description": "A control to display image content.",
+ "details": "You can use an Image control to show and scale images.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "MediaPlayerElement",
+ "PersonPicture"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media",
+ "System"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "picture",
+ "BitmapImage",
+ "photo"
+ ],
+ "docs": [
+ {
+ "title": "Image - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.image"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/images-imagebrushes"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Image",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/Image/ImagePage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Image/ImagePage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#MediaPlayerElement",
+ "microsoft/WinUI-Gallery#PersonPicture"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic image from a local file.",
+ "xaml": "\u003CImage Source=\u0022/Assets/SampleMedia/treetops.jpg\u0022 Height=\u0022100\u0022 /\u003E",
+ "gallery": {
+ "snippet": "BasicImageLocalFile.txt",
+ "source": "WinUIGallery/Samples/Image/BasicImageLocalFile.txt",
+ "name": "Basic Image Local File"
+ }
+ },
+ {
+ "header": "An image decoded to the rendering size",
+ "xaml": "\u003CImage Height=\u0022100\u0022\u003E\n \u003CImage.Source\u003E\n \u003CBitmapImage UriSource=\u0022/Assets/SampleMedia/treetops.jpg\u0022\n DecodePixelHeight=\u0022100\u0022 /\u003E\n \u003C/Image.Source\u003E\n\u003C/Image\u003E",
+ "gallery": {
+ "snippet": "ImageDecodedRenderingSize.txt",
+ "source": "WinUIGallery/Samples/Image/ImageDecodedRenderingSize.txt",
+ "name": "Decoded Rendering Size"
+ }
+ },
+ {
+ "header": "Image stretching.",
+ "xaml": "\u003CImage Stretch=\u0022None\u0022 Height=\u0022100\u0022 Width=\u0022100\u0022 Source=\u0022/Assets/SampleMedia/valley.jpg\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ImageStretching.txt",
+ "source": "WinUIGallery/Samples/Image/ImageStretching.txt",
+ "name": "Stretching"
+ }
+ },
+ {
+ "header": "Nine grid images.",
+ "xaml": "\u003CImage Source=\u0022/Assets/SampleMedia/ninegrid.gif\u0022 Height=\u002282\u0022 /\u003E\n\u003CImage Source=\u0022/Assets/SampleMedia/ninegrid.gif\u0022 NineGrid=\u00223,3,3,3\u0022 Height=\u0022164\u0022 /\u003E\n\u003CImage Source=\u0022/Assets/SampleMedia/ninegrid.gif\u0022 NineGrid=\u002230,20,30,20\u0022 Height=\u0022164\u0022 /\u003E",
+ "gallery": {
+ "snippet": "NineGridImages.txt",
+ "source": "WinUIGallery/Samples/Image/NineGridImages.txt",
+ "name": "Nine Grid Images"
+ }
+ },
+ {
+ "header": "An SVG image.",
+ "xaml": "\u003CImage Source=\u0022/Assets/SampleMedia/MirrorPCConsent.svg\u0022 Height=\u0022100\u0022 /\u003E",
+ "gallery": {
+ "snippet": "SvgImage.txt",
+ "source": "WinUIGallery/Samples/Image/SvgImage.txt",
+ "name": "Svg Image"
+ }
+ },
+ {
+ "header": "Animated GIF playback.",
+ "xaml": "\u003CStackPanel Spacing=\u002212\u0022\u003E\n \u003CTextBlock Text=\u0022An Image element automatically plays an animated GIF source.\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003CImage Height=\u002240\u0022 HorizontalAlignment=\u0022Left\u0022 Source=\u0022/Assets/SampleMedia/animated.gif\u0022/\u003E\n\n \u003CTextBlock Text=\u0022Set AutoPlay to False to prevent the GIF from playing automatically.\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003CImage Height=\u002240\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CImage.Source\u003E\n \u003CBitmapImage AutoPlay=\u0022False\u0022 UriSource=\u0022/Assets/SampleMedia/animated.gif\u0022/\u003E\n \u003C/Image.Source\u003E\n \u003C/Image\u003E\n\n \u003CTextBlock Text=\u0022Control playback manually using BitmapImage.Play() and Stop().\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003CImage Height=\u002240\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CImage.Source\u003E\n \u003CBitmapImage x:Name=\u0022ClickToPlaySource\u0022 AutoPlay=\u0022False\u0022\n UriSource=\u0022/Assets/SampleMedia/animated.gif\u0022\n ImageOpened=\u0022ClickToPlaySource_ImageOpened\u0022/\u003E\n \u003C/Image.Source\u003E\n \u003C/Image\u003E\n\u003C/StackPanel\u003E\n\n\u003C!-- The Play/Stop buttons live in ControlExample.Options so they appear in the side panel. --\u003E\n\u003CStackPanel x:Name=\u0022PlaybackButtons\u0022 Spacing=\u00228\u0022 Visibility=\u0022Collapsed\u0022\u003E\n \u003CButton Content=\u0022Play\u0022 Click=\u0022{x:Bind ClickToPlaySource.Play}\u0022/\u003E\n \u003CButton Content=\u0022Stop\u0022 Click=\u0022{x:Bind ClickToPlaySource.Stop}\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "code": "private void ClickToPlaySource_ImageOpened(object sender, RoutedEventArgs e)\n{\n // BitmapImage.IsAnimatedBitmap is only valid after ImageOpened has been raised.\n if (ClickToPlaySource.IsAnimatedBitmap)\n {\n PlaybackButtons.Visibility = Visibility.Visible;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AnimatedGif.txt",
+ "source": "WinUIGallery/Samples/Image/AnimatedGif.txt",
+ "name": "Animated Gif"
+ }
+ }
+ ]
+ },
+ {
+ "id": "implicittransition",
+ "name": "Implicit Transitions",
+ "description": "Use Implicit Transitions to automatically animate changes to properties.",
+ "details": "Use Implicit Transitions to automatically animate changes to properties.",
+ "apiNamespace": "Microsoft.UI.Xaml",
+ "relatedControls": [
+ "Page Transitions",
+ "Theme Transitions"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Input",
+ "Microsoft.UI.Xaml.Media",
+ "System",
+ "System.Numerics",
+ "Windows.Foundation.Metadata"
+ ],
+ "curatedKeywords": [
+ "implicit animation",
+ "transition",
+ "property animation"
+ ],
+ "docs": [
+ {
+ "title": "Transitions - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.uielement.transitions#Windows_UI_Xaml_UIElement_Transitions"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/motion-in-practice#implicit-animations"
+ },
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ImplicitTransition",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#PageTransition",
+ "microsoft/WinUI-Gallery#ThemeTransition"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Automatically animate changes to Opacity",
+ "xaml": "\u003C!-- Automatically animate changes to Opacity --\u003E\n\u003CRectangle x:Name=\u0022rectangle\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Opacity=\u00220.5\u0022\u003E\n \u003CRectangle.OpacityTransition\u003E\n \u003CScalarTransition /\u003E\n \u003C/Rectangle.OpacityTransition\u003E\n\u003C/Rectangle\u003E",
+ "code": "private void button_Click(object sender, RoutedEventArgs e)\n{\n rectangle.Opacity = 1.0;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionAutomaticallyAnimateChangesOpacity.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionAutomaticallyAnimateChangesOpacity.txt",
+ "name": "Automatically Animate Changes Opacity"
+ }
+ },
+ {
+ "header": "Automatically animate changes to Rotation",
+ "xaml": "\u003C!-- Automatically animate changes to Rotation --\u003E\n\u003CRectangle x:Name=\u0022rectangle\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Rotation=\u00220\u0022 \u003E\n \u003CRectangle.RotationTransition\u003E\n \u003CScalarTransition /\u003E\n \u003C/Rectangle.RotationTransition\u003E\n\u003C/Rectangle\u003E",
+ "code": "private void button_Click(object sender, RoutedEventArgs e)\n{\n rectangle.Rotation = 45; // Clockwise, in degrees\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionAutomaticallyAnimateChangesRotation.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionAutomaticallyAnimateChangesRotation.txt",
+ "name": "Automatically Animate Changes Rotation"
+ }
+ },
+ {
+ "header": "Automatically animate changes to Scale",
+ "xaml": "\u003C!-- Automatically animate changes to Scale --\u003E\n\u003CRectangle x:Name=\u0022rectangle\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Scale=\u00221,1,1\u0022 \u003E\n \u003CRectangle.ScaleTransition\u003E\n \u003CVector3Transition /\u003E\n \u003C/Rectangle.ScaleTransition\u003E\n\u003C/Rectangle\u003E",
+ "code": "using System.Numerics;\nprivate void button_Click(object sender, RoutedEventArgs e)\n{\n rectangle.Scale = new Vector3(1, 1, 1);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionAutomaticallyAnimateChangesScale.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionAutomaticallyAnimateChangesScale.txt",
+ "name": "Automatically Animate Changes Scale"
+ }
+ },
+ {
+ "header": "Automatically animate changes to Translation",
+ "xaml": "\u003C!-- Automatically animate changes to Translation --\u003E\n\u003CRectangle x:Name=\u0022rectangle\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Translation=\u00220,0,0\u0022 \u003E\n \u003CRectangle.TranslationTransition\u003E\n \u003CVector3Transition /\u003E\n \u003C/Rectangle.TranslationTransition\u003E\n\u003C/Rectangle\u003E",
+ "code": "using System.Numerics;\nprivate void button_Click(object sender, RoutedEventArgs e)\n{\n rectangle.Translation = new Vector3(1, 1, 1);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionAutomaticallyAnimateChangesTranslation.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionAutomaticallyAnimateChangesTranslation.txt",
+ "name": "Automatically Animate Changes Translation"
+ }
+ },
+ {
+ "header": "Implicitly animate when the Background changes",
+ "xaml": "\u003CContentPresenter x:Name=\u0022BrushPresenter\u0022 Background=\u0022Blue\u0022 Width=\u002250\u0022 Height=\u002250\u0022\u003E\n \u003CContentPresenter.BackgroundTransition\u003E\n \u003CBrushTransition /\u003E\n \u003C/ContentPresenter.BackgroundTransition\u003E\n\u003C/ContentPresenter\u003E",
+ "code": "private void button_Click(object sender, RoutedEventArgs e)\n{\n // Note that this is a new brush instance, not a new color on the same brush.\n if (HasBlueBackground(BrushPresenter))\n {\n BrushPresenter.Background = new SolidColorBrush(Yellow);\n }\n else\n {\n BrushPresenter.Background = new SolidColorBrush(Blue);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionImplicitlyAnimateBackgroundChanges.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionImplicitlyAnimateBackgroundChanges.txt",
+ "name": "Implicitly Animate Background Changes"
+ }
+ },
+ {
+ "header": "Implicitly animate when the Grid\u0027s theme changes",
+ "xaml": "\u003CGrid x:Name=\u0022ThemeExampleGrid\u0022 Background=\u0022{ThemeResource SolidBackgroundFillColorBaseBrush}\u0022 \u003E\n \u003CGrid.BackgroundTransition\u003E\n \u003CBrushTransition /\u003E\n \u003C/Grid.BackgroundTransition\u003E\n \u003CStackPanel Margin=\u002212\u0022 Spacing=\u00226\u0022\u003E\n \u003CTextBlock Text=\u0022Lorem Ipsum\u0022 Style=\u0022{ThemeResource SubtitleTextBlockStyle}\u0022 /\u003E\n \u003CTextBlock Text=\u0022The background of this grid animates when the theme changes.\u0022 TextWrapping=\u0022WrapWholeWords\u0022 /\u003E\n \u003CButton Content=\u0022Button\u0022 /\u003E\n \u003CCheckBox Content=\u0022CheckBox\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/Grid\u003E",
+ "code": "private void ThemeButton_Click(object sender, RoutedEventArgs e)\n{\n ThemeExampleGrid.RequestedTheme = ThemeExampleGrid.RequestedTheme == ElementTheme.Dark ? ElementTheme.Light : ElementTheme.Dark;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ImplicitTransitionImplicitlyAnimateGridTheme.txt",
+ "source": "WinUIGallery/Samples/ImplicitTransition/ImplicitTransitionImplicitlyAnimateGridTheme.txt",
+ "name": "Implicitly Animate Grid Theme"
+ }
+ }
+ ]
+ },
+ {
+ "id": "infobadge",
+ "name": "InfoBadge",
+ "description": "An non-intrusive UI to display notifications or bring focus to an area.",
+ "details": "Badging is a non-intrusive and intuitive way to display notifications or bring focus to an area within an app - whether that be for notifications, indicating new content, or showing an alert.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "InfoBar",
+ "TeachingTip",
+ "Badge notifications"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "notification dot",
+ "count badge"
+ ],
+ "docs": [
+ {
+ "title": "InfoBadge - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.infobadge"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/info-badge"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "InfoBadge",
+ "group": {
+ "id": "StatusAndInfo",
+ "title": "Status \u0026 info"
+ },
+ "page": "WinUIGallery/Samples/InfoBadge/InfoBadgePage.xaml",
+ "codeBehind": "WinUIGallery/Samples/InfoBadge/InfoBadgePage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#BadgeNotificationManager",
+ "microsoft/WinUI-Gallery#InfoBar",
+ "microsoft/WinUI-Gallery#TeachingTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "InfoBadge embedded in NavigationView",
+ "xaml": "\u003CNavigationViewItem x:Name=\u0022InboxPage\u0022 Content=\u0022Inbox\u0022 Icon=\u0022Mail\u0022 AutomationProperties.Name=\u0022Inbox, 5 notifications\u0022\u003E\n \u003CNavigationViewItem.InfoBadge\u003E\n \u003CInfoBadge x:Name=\u0022infoBadge1\u0022 Value=\u00225\u0022 Opacity=\u0022{x:Bind InfoBadgeOpacity, Mode=OneWay}\u0022/\u003E\n \u003C/NavigationViewItem.InfoBadge\u003E\n\u003C/NavigationViewItem\u003E",
+ "gallery": {
+ "snippet": "InfobadgeEmbeddedNavigationview.txt",
+ "source": "WinUIGallery/Samples/InfoBadge/InfobadgeEmbeddedNavigationview.txt",
+ "name": "Embedded Navigationview"
+ }
+ },
+ {
+ "header": "Different InfoBadge Styles",
+ "xaml": "\u003CStackPanel Orientation=\u0022Horizontal\u0022 Spacing=\u002220\u0022 HorizontalAlignment=\u0022Center\u0022\u003E\n \u003CInfoBadge x:Name=\u0022infoBadge2\u0022 HorizontalAlignment=\u0022Right\u0022/\u003E\n \u003CInfoBadge x:Name=\u0022infoBadge3\u0022 HorizontalAlignment=\u0022Right\u0022 Value=\u002210\u0022 /\u003E\n \u003CInfoBadge x:Name=\u0022infoBadge4\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "DifferentInfobadgeStyles.txt",
+ "source": "WinUIGallery/Samples/InfoBadge/DifferentInfobadgeStyles.txt",
+ "name": "Different Infobadge Styles",
+ "xamlPlaceholdersDropped": [
+ "Style"
+ ]
+ }
+ },
+ {
+ "header": "Placing an InfoBadge Inside Another Control",
+ "xaml": "\u003CButton Padding=\u00220\u0022 Width=\u0022200\u0022 Height=\u002260\u0022 ToolTipService.ToolTip=\u0022Refresh required\u0022\n HorizontalAlignment=\u0022Center\u0022 HorizontalContentAlignment=\u0022Stretch\u0022 VerticalContentAlignment=\u0022Stretch\u0022\u003E\n \u003CGrid HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Stretch\u0022 Width=\u0022Auto\u0022 Height=\u0022Auto\u0022\u003E\n \u003CSymbolIcon Symbol=\u0022Sync\u0022 HorizontalAlignment=\u0022Center\u0022/\u003E\n \u003CInfoBadge Background=\u0022#C42B1C\u0022 HorizontalAlignment=\u0022Right\u0022 VerticalAlignment=\u0022Top\u0022\u003E\n \u003CInfoBadge.IconSource\u003E\n \u003CFontIconSource FontFamily=\u0022{StaticResource SymbolThemeFontFamily}\u0022 Glyph=\u0022\u0026#xF13C;\u0022 /\u003E\n \u003C/InfoBadge.IconSource\u003E\n \u003C/InfoBadge\u003E\n \u003C/Grid\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "PlacingInfobadgeInsideAnother.txt",
+ "source": "WinUIGallery/Samples/InfoBadge/PlacingInfobadgeInsideAnother.txt",
+ "name": "Placing Infobadge Inside Another"
+ }
+ },
+ {
+ "header": "InfoBadge with Dynamic Value",
+ "xaml": "\u003CInfoBadge Value=\u0022{Binding ElementName=ValueNumberBox, Path=Value, Mode=TwoWay}\u0022 /\u003E\n\u003CNumberBox x:Name=\u0022ValueNumberBox\u0022 Header=\u0022InfoBadge Value\u0022 Value=\u00221\u0022 Minimum=\u0022-1\u0022\n SpinButtonPlacementMode=\u0022Inline\u0022 ValueChanged=\u0022ValueNumberBox_ValueChanged\u0022 /\u003E",
+ "code": "private void ValueNumberBox_ValueChanged(Microsoft.UI.Xaml.Controls.NumberBox sender, Microsoft.UI.Xaml.Controls.NumberBoxValueChangedEventArgs args)\n{\n if((int)args.NewValue \u003E= -1)\n {\n DynamicInfoBadge.Value = (int)args.NewValue;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "InfobadgeDynamicValue.txt",
+ "source": "WinUIGallery/Samples/InfoBadge/InfobadgeDynamicValue.txt",
+ "name": "Dynamic Value"
+ }
+ }
+ ]
+ },
+ {
+ "id": "infobar",
+ "name": "InfoBar",
+ "description": "An inline message to display app-wide status change information.",
+ "details": "Use an InfoBar control when a user should be informed of, acknowledge, or take action on a changed application state. By default the notification will remain in the content area until closed by the user but will not necessarily break user flow.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "TeachingTip",
+ "ContentDialog"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "notification",
+ "status message",
+ "alert",
+ "banner"
+ ],
+ "docs": [
+ {
+ "title": "InfoBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.infobar"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/infobar"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "InfoBar",
+ "group": {
+ "id": "StatusAndInfo",
+ "title": "Status \u0026 info"
+ },
+ "page": "WinUIGallery/Samples/InfoBar/InfoBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/InfoBar/InfoBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ContentDialog",
+ "microsoft/WinUI-Gallery#TeachingTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A closable InfoBar with options to change its Severity.",
+ "xaml": "\u003CInfoBar \n IsOpen=\u0022{x:Bind TestInfoBar1.IsOpen, Mode=TwoWay}\u0022\n Title=\u0022Title\u0022\n Message=\u0022Essential app message for your users to be informed of, acknowledge, or take action on.\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ClosableInfobarOptionsChange.txt",
+ "source": "WinUIGallery/Samples/InfoBar/ClosableInfobarOptionsChange.txt",
+ "name": "Closable Infobar Options Change",
+ "xamlPlaceholdersDropped": [
+ "Severity"
+ ]
+ }
+ },
+ {
+ "header": "A closable InfoBar with a long or short message and various buttons",
+ "xaml": "\u003CInfoBar \n IsOpen=\u0022{x:Bind TestInfoBar2.IsOpen, Mode=TwoWay}\u0022\n Title=\u0022Title\u0022\n Message=\u0022\u0022 \u003E\n \n\u003C/InfoBar\u003E",
+ "gallery": {
+ "snippet": "ClosableInfobarLongShort.txt",
+ "source": "WinUIGallery/Samples/InfoBar/ClosableInfobarLongShort.txt",
+ "name": "Closable Infobar Long Short"
+ }
+ },
+ {
+ "header": "A closable InfoBar with options to display the close button and icon",
+ "xaml": "\u003CInfoBar \n IsOpen=\u0022{x:Bind TestInfoBar3.IsOpen, Mode=TwoWay}\u0022\n IsIconVisible=\u0022{x:Bind TestInfoBar3.IsIconVisible, Mode=TwoWay}\u0022 \n IsClosable=\u0022{x:Bind TestInfoBar3.IsClosable, Mode=TwoWay}\u0022\n Title=\u0022Title\u0022\n Message=\u0022Essential app message for your users to be informed of, acknowledge, or take action on.\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ClosableInfobarOptionsDisplay.txt",
+ "source": "WinUIGallery/Samples/InfoBar/ClosableInfobarOptionsDisplay.txt",
+ "name": "Closable Infobar Options Display"
+ }
+ }
+ ]
+ },
+ {
+ "id": "itemsrepeater",
+ "name": "ItemsRepeater",
+ "description": "A flexible, primitive control for data-driven layouts.",
+ "details": "The ItemsRepeater is like a markup-based loop that supports virtualization.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ItemsView",
+ "ScrollView",
+ "ScrollViewer",
+ "ListView",
+ "GridView"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Automation",
+ "Microsoft.UI.Xaml.Automation.Peers",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives",
+ "Microsoft.UI.Xaml.Hosting",
+ "Microsoft.UI.Xaml.Input",
+ "System",
+ "System.Collections",
+ "System.Collections.Generic",
+ "System.Collections.ObjectModel",
+ "System.Collections.Specialized",
+ "System.Linq"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "data layout",
+ "virtualization"
+ ],
+ "docs": [
+ {
+ "title": "ItemsRepeater - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemsrepeater"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/items-repeater"
+ },
+ {
+ "title": "StackLayout - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.stacklayout"
+ },
+ {
+ "title": "UniformGridLayout - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.uniformgridlayout"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ItemsRepeater",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ItemsView",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#ScrollView",
+ "microsoft/WinUI-Gallery#ScrollViewer"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic, non-interactive items laid out by ItemsRepeater",
+ "xaml": "\u003C!-- The ItemsRepeater and ScrollViewer used: --\u003E\n\u003CScrollViewer HorizontalScrollBarVisibility=\u0022Auto\u0022 \n HorizontalScrollMode=\u0022Auto\u0022 \n IsVerticalScrollChainingEnabled=\u0022False\u0022\n MaxHeight=\u0022500\u0022\u003E\n \u003CItemsRepeater\n ItemsSource=\u0022{x:Bind BarItems}\u0022\n Layout=\u0022{StaticResource VerticalStackLayout}\u0022\n ItemTemplate=\u0022{StaticResource HorizontalBarTemplate}\u0022 /\u003E\n\u003C/ScrollViewer\u003E\n \n\u003C!-- The Layout specifications used: --\u003E\n \n \n\u003C!-- The DataTemplate used: HorizontalBarTemplate--\u003E\n ",
+ "code": "// The ItemsSource used is a list of custom-class Bar objects called BarItems\n\npublic class Bar\n{\n public Bar(double length, int max)\n {\n Length = length;\n MaxLength = max;\n\n Height = length / 4;\n MaxHeight = max / 4;\n\n Diameter = length / 6;\n MaxDiameter = max / 6;\n }\n public double Length { get; set; }\n public int MaxLength { get; set; }\n\n public double Height { get; set; }\n public double MaxHeight { get; set; }\n\n public double Diameter { get; set; }\n public double MaxDiameter { get; set; }\n}\n\npublic ObservableCollection\u003CBar\u003E BarItems;\nprivate int MaxLength = 425;\n\nprivate void InitializeData()\n{\n if (BarItems == null)\n {\n BarItems = new ObservableCollection\u003CBar\u003E();\n }\n BarItems.Add(new Bar(300, this.MaxLength));\n BarItems.Add(new Bar(25, this.MaxLength));\n BarItems.Add(new Bar(175, this.MaxLength));\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsRepeaterBasicNonInteractiveItems.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterBasicNonInteractiveItems.txt",
+ "name": "Basic Non Interactive Items",
+ "xamlPlaceholdersDropped": [
+ "SampleCodeLayout",
+ "SampleCodeDT"
+ ]
+ }
+ },
+ {
+ "header": "Virtualizing, scrollable list of items laid out by ItemsRepeater",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003C!-- The ItemsRepeater and ScrollViewer used: --\u003E\n\u003CScrollViewer x:Name=\u0022scrollViewer\u0022\n Height=\u0022400\u0022\n IsVerticalScrollChainingEnabled=\u0022False\u0022\n Padding=\u00220,0,16,0\u0022\u003E\n \u003CItemsRepeater\n ItemsSource=\u0022{x:Bind NumberedItems}\u0022\n Layout=\u0022{StaticResource MyFeedLayout}\u0022\n ItemTemplate=\u0022{StaticResource SimpleItemTemplate}\u0022 /\u003E\n\u003C/ScrollViewer\u003E \n \n\u003C!-- The Layout specifications used: --\u003E\n \n \n\u003C!-- The ItemTemplate is bound to a DataTemplateSelector called MyDataTemplateSelector. \nMyDataTemplateSelector is defined in the code-behind to return the Accent DataTemplate \nfor odd-numbered-items, and returns the Normal DataTemplate for even-numbered-items \n(shown in C# code-behind section below). The two data templates and the XAML declaration\nof MyDataTemplateSelector are below: --\u003E\n\n\u003CMyDataTemplateSelector x:Key=\u0022MyDataTemplateSelector\u0022\n Normal=\u0022{StaticResource NormalItemTemplate}\u0022\n Accent=\u0022{StaticResource AccentItemTemplate}\u0022/\u003E \n \n\u003CDataTemplate x:Key=\u0022NormalItemTemplate\u0022 x:DataType=\u0022x:Int32\u0022\u003E\n \u003CButton HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Stretch\u0022 \n\t Background=\u0022{ThemeResource SystemChromeLowColor}\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind}\u0022 /\u003E\n \u003C/Button\u003E\n\u003C/DataTemplate\u003E\n\n\u003CDataTemplate x:Key=\u0022AccentItemTemplate\u0022 x:DataType=\u0022x:Int32\u0022\u003E\n \u003CButton HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Stretch\u0022 \n\t Background=\u0022{ThemeResource SystemAccentColor}\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind}\u0022 /\u003E\n \u003C/Button\u003E\n\u003C/DataTemplate\u003E\n \n\u003C!-- The ItemsSource for this ItemsRepeater is a list of integers called NumberedItems.--\u003E\n \n\u003C!-- ActivityFeedLayout is a custom designed virtualizing layout that loads images only as you come \naccross them, defined in the code-behind. View the WinUI Gallery source code to see more\ndetails about this custom layout. --\u003E",
+ "code": "// C# Code-behind\n\npublic class MyDataTemplateSelector : DataTemplateSelector\n{\n public DataTemplate? Normal { get; set; }\n public DataTemplate? Accent { get; set; }\n\n protected override DataTemplate? SelectTemplateCore(object item)\n {\n if ((int)item % 2 == 0)\n {\n return Normal;\n }\n else\n {\n return Accent;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsRepeaterVirtualizingScrollableListItems.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterVirtualizingScrollableListItems.txt",
+ "name": "Virtualizing Scrollable List Items",
+ "xamlPlaceholdersDropped": [
+ "SampleCodeLayout2"
+ ]
+ }
+ },
+ {
+ "header": "Use FlowLayout with ItemsRepeater to wrap and virtualize a large collection.",
+ "xaml": "\u003CScrollViewer Width=\u0022520\u0022 Height=\u0022320\u0022\n HorizontalScrollMode=\u0022Disabled\u0022\n VerticalScrollMode=\u0022Enabled\u0022\u003E\n \u003CItemsRepeater ItemsSource=\u0022{x:Bind FlowLayoutItems}\u0022\n ItemTemplate=\u0022{StaticResource FlowItemTemplate}\u0022\u003E\n \u003CItemsRepeater.Layout\u003E\n \u003CFlowLayout\n LineAlignment=\u0022Start\u0022\n MinItemSpacing=\u00228\u0022\n LineSpacing=\u00228\u0022/\u003E\n \u003C/ItemsRepeater.Layout\u003E\n \u003C/ItemsRepeater\u003E\n\u003C/ScrollViewer\u003E\n\n\u003CDataTemplate x:Key=\u0022FlowItemTemplate\u0022 x:DataType=\u0022local:FlowLayoutItem\u0022\u003E\n \u003CBorder Width=\u002296\u0022 Height=\u002264\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Label}\u0022/\u003E\n \u003C/Border\u003E\n\u003C/DataTemplate\u003E",
+ "code": "public IReadOnlyList\u003CFlowLayoutItem\u003E FlowLayoutItems { get; } = Enumerable.Range(1, 500)\n .Select(index =\u003E new FlowLayoutItem($\u0022Item {index}\u0022))\n .ToList();\n\npublic sealed record FlowLayoutItem(string Label);",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "FlowLayoutVirtualization.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/FlowLayoutVirtualization.txt",
+ "name": "Flow Layout Virtualization",
+ "xamlPlaceholdersDropped": [
+ "Orientation"
+ ]
+ }
+ },
+ {
+ "header": "ItemsRepeater with mixed-type collection",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003C!-- This is the ItemsRepeater used in this example: --\u003E\n\u003CItemsRepeater x:Name=\u0022MixedTypeRepeater\u0022 \n Margin=\u00220,0,12,0\u0022\n HorizontalAlignment=\u0022Stretch\u0022\n ItemTemplate=\u0022{StaticResource StringOrIntTemplateSelector}\u0022\u003E\n\n \u003CItemsRepeater.Layout\u003E\n \u003CUniformGridLayout MinItemWidth=\u0022200\u0022 MinItemHeight=\u0022200\u0022/\u003E\n \u003C/ItemsRepeater.Layout\u003E\n\u003C/ItemsRepeater\u003E\n\n\u003C!-- The ItemsSource is bound in the C# code-behind to an ObservableCollection called \nStringsAndInts. StringsAndInts has both string objects and integer objects. The ItemTemplate\nis a DataTemplateSelector called StringOrIntTemplateSelector, and is defined in the \ncode-behind and shown in the C# code-behind section below. The layout is a simple \nUniformGridLayout where each item is a 200x200 square. --\u003E\n \n\u003C!-- StringOrIntTemplateSelector assesses the type of an item, and returns StringDataTemplate if \nthe item is a string, and IntDataTemplate if the item is an integer. \nThe XAML code directly below binds the DataTemplateSelector to those two data templates, and \ndefines each of them: --\u003E\n \n\u003CStringOrIntTemplateSelector x:Key=\u0022StringOrIntTemplateSelector\u0022\n StringTemplate=\u0022{StaticResource StringDataTemplate}\u0022\n IntTemplate=\u0022{StaticResource IntDataTemplate}\u0022/\u003E \n \n\u003CDataTemplate x:Key=\u0022StringDataTemplate\u0022 x:DataType=\u0022x:String\u0022\u003E\n \u003CGrid Background=\u0022{ThemeResource SystemControlBackgroundAccentBrush}\u0022 Margin=\u002210\u0022\u003E\n \u003CTextBlock Padding=\u002210\u0022 Text=\u0022{x:Bind}\u0022 \n Foreground=\u0022{ThemeResource SystemControlForegroundChromeWhiteBrush}\u0022\n HorizontalAlignment=\u0022Center\u0022 TextWrapping=\u0022Wrap\u0022 \n VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E\n\n\u003CDataTemplate x:Key=\u0022IntDataTemplate\u0022 x:DataType=\u0022x:Int32\u0022\u003E\n \u003CGrid Background=\u0022{ThemeResource SystemControlBackgroundChromeMediumBrush}\u0022 Margin=\u002210\u0022\u003E\n \u003CTextBlock Padding=\u002210\u0022 Text=\u0022{x:Bind}\u0022 \n Style=\u0022{StaticResource HeaderTextBlockStyle}\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E",
+ "code": "// C# code-behind\n\npublic class StringOrIntTemplateSelector : DataTemplateSelector\n{\n // Define the (currently empty) data templates to return\n // These will be \u0022filled-in\u0022 in the XAML code.\n public DataTemplate? StringTemplate { get; set; }\n\n public DataTemplate? IntTemplate { get; set; }\n\n protected override DataTemplate? SelectTemplateCore(object item)\n {\n // Return the correct data template based on the item\u0027s type.\n if (item.GetType() == typeof(String))\n {\n return StringTemplate;\n }\n else if (item.GetType() == typeof(int))\n {\n return IntTemplate;\n }\n else\n {\n return null;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsrepeaterMixedTypeCollection.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/ItemsrepeaterMixedTypeCollection.txt",
+ "name": "Mixed Type Collection"
+ }
+ },
+ {
+ "header": "Animated Scrolling and Content Display",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003C!-- The below code shows the XAML for the ItemsRepeater as well as the\ncolor-changing rectangle besides it. --\u003E\n\n\u003CGrid\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u00221*\u0022/\u003E\n \u003CColumnDefinition Width=\u00221*\u0022/\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n\n \u003CScrollViewer x:Name=\u0022Animated_ScrollViewer\u0022 \n Grid.Column=\u00220\u0022\n Height=\u0022175\u0022\n Width=\u0022250\u0022\n ViewChanging=\u0022Animated_ScrollViewer_ViewChanging\u0022\u003E\n \u003CItemsRepeater x:Name=\u0022animatedScrollRepeater\u0022 \u003E\n \u003CItemsRepeater.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022x:String\u0022\u003E\n \u003CButton Content=\u0022{x:Bind}\u0022\n Background=\u0022{x:Bind}\u0022\n Click=\u0022Animated_GotItem\u0022 \n GotFocus=\u0022Animated_GotItem\u0022 \n HorizontalAlignment=\u0022Stretch\u0022\n Foreground=\u0022{ThemeResource ButtonForeground}\u0022/\u003E\n \u003C/DataTemplate\u003E\n \u003C/ItemsRepeater.ItemTemplate\u003E\n \u003C/ItemsRepeater\u003E\n \u003C/ScrollViewer\u003E\n\n \u003CRectangle x:Name=\u0022colorRectangle\u0022\n Grid.Column=\u00221\u0022\n Stroke=\u0022Black\u0022\n Height=\u0022150\u0022\n Width=\u0022150\u0022\n Margin=\u002210,0,0,0\u0022/\u003E\n\u003C/Grid\u003E",
+ "code": "// C# Code\n\n// Initialization code\n\nprivate double AnimatedBtnHeight;\nprivate Microsoft.UI.Xaml.Thickness AnimatedBtnMargin;\n\nprivate void InitializeData()\n{\n\n IList\u003Cstring\u003E colors = new List\u003CString\u003E()\n {\n \u0022Blue\u0022,\n \u0022BlueViolet\u0022,\n \u0022Crimson\u0022,\n \u0022DarkCyan\u0022,\n \u0022DarkGoldenrod\u0022,\n \u0022DarkMagenta\u0022,\n \u0022DarkOliveGreen\u0022,\n \u0022DarkRed\u0022,\n \u0022DarkSlateBlue\u0022,\n \u0022DeepPink\u0022,\n \u0022IndianRed\u0022,\n \u0022MediumSlateBlue\u0022,\n \u0022Maroon\u0022,\n \u0022MidnightBlue\u0022,\n \u0022Peru\u0022,\n \u0022SaddleBrown\u0022,\n \u0022SteelBlue\u0022,\n \u0022OrangeRed\u0022,\n \u0022Firebrick\u0022,\n \u0022DarkKhaki\u0022\n };\n\n animatedScrollRepeater.ItemsSource = colors;\n animatedScrollRepeater.ElementPrepared \u002B= OnElementPrepared;\n}\n\n// Animation code\n\nprivate void Animated_GotItem(object sender, RoutedEventArgs e)\n{\n if (sender is not Button senderBtn)\n {\n return;\n }\n\n // When the clicked item has been recieved, bring it to the middle of the viewport.\n senderBtn.StartBringIntoView(new BringIntoViewOptions()\n {\n VerticalAlignmentRatio = 0.5,\n AnimationDesired = true,\n });\n\n // Update corresponding rectangle with selected color\n colorRectangle.Fill = senderBtn.Background;\n}\n\n/* This function occurs each time an element is made ready for use.\n* This is necessary for virtualization. */\nprivate void OnElementPrepared(Microsoft.UI.Xaml.Controls.ItemsRepeater sender, \n Microsoft.UI.Xaml.Controls.ItemsRepeaterElementPreparedEventArgs args)\n{\n var item = ElementCompositionPreview.GetElementVisual(args.Element);\n var svVisual = ElementCompositionPreview.GetElementVisual(Animated_ScrollViewer);\n var scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(Animated_ScrollViewer);\n\n var scaleExpresion = scrollProperties.Compositor.CreateExpressionAnimation();\n scaleExpresion.SetReferenceParameter(\u0022svVisual\u0022, svVisual);\n scaleExpresion.SetReferenceParameter(\u0022scrollProperties\u0022, scrollProperties);\n scaleExpresion.SetReferenceParameter(\u0022item\u0022, item);\n\n // Scale the item based on the distance of the item relative to the center of the viewport.\n scaleExpresion.Expression = \u00221 - abs((svVisual.Size.Y/2 - scrollProperties.Translation.Y) \n - (item.Offset.Y \u002B item.Size.Y/2))*(.25/(svVisual.Size.Y/2))\u0022;\n\n // Animate the item based on its distance to the center of the viewport.\n item.StartAnimation(\u0022Scale.X\u0022, scaleExpresion);\n item.StartAnimation(\u0022Scale.Y\u0022, scaleExpresion);\n var centerPointExpression = scrollProperties.Compositor.CreateExpressionAnimation();\n centerPointExpression.SetReferenceParameter(\u0022item\u0022, item);\n centerPointExpression.Expression = \u0022Vector3(item.Size.X/2, item.Size.Y/2, 0)\u0022;\n item.StartAnimation(\u0022CenterPoint\u0022, centerPointExpression);\n}\n\n/* This function identifies the item that\u0027s currently in the middle of the viewport,\nand sets the rectangle to match its color. */\nprivate void Animated_ScrollViewer_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)\n{\n if (GetSelectedItemFromViewport() is not Button selectedItem)\n {\n return;\n }\n\n // Update corresponding rectangle with selected color\n colorRectangle.Fill = selectedItem.Background;\n}\n\n// The remainder of these functions are helper functions for the ViewChanging function:\n\n// Find centerpoint of ScrollViewer\nprivate double CenterPointOfViewportInExtent()\n{\n return Animated_ScrollViewer.VerticalOffset \u002B Animated_ScrollViewer.ViewportHeight / 2;\n}\n\n// Find index of the item that\u0027s at the center of the viewport\nprivate int GetSelectedIndexFromViewport()\n{\n int selectedItemIndex = (int)Math.Floor(CenterPointOfViewportInExtent() \n / ((double)AnimatedBtnMargin.Top \u002B AnimatedBtnHeight));\n selectedItemIndex %= animatedScrollRepeater.ItemsSourceView.Count;\n return selectedItemIndex;\n}\n\n// Return item that\u0027s at the center of the viewport.\nprivate object? GetSelectedItemFromViewport()\n{\n var selectedIndex = GetSelectedIndexFromViewport();\n var selectedElement = animatedScrollRepeater.TryGetElement(selectedIndex) as Button;\n return selectedElement;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsRepeaterAnimatedScrollingContentDisplay.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterAnimatedScrollingContentDisplay.txt",
+ "name": "Animated Scrolling Content Display"
+ }
+ },
+ {
+ "header": "Virtualized, Content-Heavy Layout with Filtering and Sorting",
+ "code": "// C# Code\n\n// ========================== Recipe class used for items ========================== \npublic class Recipe\n{\n public int Num { get; set; }\n public string Ingredients { get; set; } = string.Empty;\n public List\u003Cstring\u003E IngList { get; set; } = [];\n public string Name { get; set; } = string.Empty;\n public string Color { get; set; } = string.Empty;\n public int numIngredients\n {\n get\n {\n return IngList.Count();\n }\n }\n\n public void RandomizeIngredients()\n {\n // To give the items different heights for visual variety, give recipes \n // random numbers of random \u0022extra\u0022 ingredients\n Random rndNum = new Random();\n Random rndIng = new Random();\n\n ObservableCollection\u003Cstring\u003E extras = new ObservableCollection\u003Cstring\u003E{\n \u0022Garlic\u0022,\n \u0022Lemon\u0022,\n \u0022Butter\u0022,\n \u0022Lime\u0022,\n \u0022Feta Cheese\u0022,\n \u0022Parmesan Cheese\u0022,\n \u0022Breadcrumbs\u0022};\n for (int i =0; i \u003C rndNum.Next(0,4); i\u002B\u002B)\n {\n string newIng = extras[rndIng.Next(0, 6)];\n // If the ingredient is not already present in the recipe, add it\n if (!IngList.Contains(newIng))\n {\n Ingredients \u002B= \u0022\\n\u0022 \u002B newIng;\n IngList.Add(newIng);\n }\n }\n\n }\n}\n\n// ========================== Data source class ========================== \n/* To hold the recipe items, a data source class was created called MyItemsSource. The class\n inherits from IList and IKeyIndexMapping interfaces, basically creating a collection class \n that can easily filter and sort its items. Important methods are shown below, but full source\n code can be found in WinUI Gallery repo. See the linked ItemsRepeater guidance documentation as\n well for a full tutorial on how to implement this type of class. */\n\npublic class MyItemsSource : IList, \n Microsoft.UI.Xaml.Controls.IKeyIndexMapping, \n INotifyCollectionChanged\n{\n private List\u003CRecipe\u003E inner = new List\u003CRecipe\u003E();\n\n public MyItemsSource(IEnumerable\u003CRecipe\u003E collection)\n {\n InitializeCollection(collection);\n }\n\n public void InitializeCollection(IEnumerable\u003CRecipe\u003E collection)\n {\n inner.Clear();\n if (collection != null)\n {\n inner.AddRange(collection); \n }\n\n if (CollectionChanged != null)\n {\n CollectionChanged?.Invoke(\n this, \n new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));\n }\n }\n\n //...\n\n public string KeyFromIndex(int index)\n {\n return inner[index].Num.ToString();\n }\n\n public int IndexFromKey(string key)\n {\n foreach (Recipe item in inner)\n {\n if (item.Num.ToString() == key)\n {\n return inner.IndexOf(item);\n }\n }\n return -1;\n }\n // ...\n\n}\n\n// ========================== Initialization code ==========================\n\npublic MyItemsSource filteredRecipeData = new MyItemsSource(null);\npublic List\u003CRecipe\u003E staticRecipeData;\n\nprivate void InitializeData()\n{\n // ...\n // Create a list of Recipe objects, initializing each of them with a random number,\n // correlating name, and random color to associate with it.\n var rnd = new Random();\n List\u003CRecipe\u003E tempList = new List\u003CRecipe\u003E(\n Enumerable.Range(0, 1000).Select(k =\u003E\n new Recipe\n {\n Num = k,\n Name = \u0022Recipe \u0022 \u002B k.ToString(),\n Color = colors[k % 15 \u002B 1]\n }));\n\n // The lists fruits, vegetables, grains, and proteins were all populated with strings. \n // This loop goes through each Recipe item and populates its ingredients list with one \n // string from each list/category, then randomizes the ingredients list by adding extras. \n foreach (Recipe rec in tempList)\n {\n string fruitOption = fruits[rnd.Next(0, 6)];\n string vegOption = vegetables[rnd.Next(0, 6)];\n string grainOption = grains[rnd.Next(0, 6)];\n string proteinOption = proteins[rnd.Next(0, 6)];\n rec.Ingredients = \u0022\\n\u0022 \u002B fruitOption \u002B \u0022\\n\u0022 \u002B vegOption \u002B \u0022\\n\u0022 \u002B \n grainOption \u002B \u0022\\n\u0022 \u002B proteinOption;\n rec.IngList = new List\u003Cstring\u003E() { fruitOption, vegOption, grainOption, proteinOption };\n rec.RandomizeIngredients();\n }\n\n // The custom MyItemsSource object, filteredRecipeData, is initialized.\n filteredRecipeData.InitializeCollection(tempList);\n // A static list of the original recipe data is saved to use for filtering.\n staticRecipeData = new List\u003CRecipe\u003E(tempList);\n // The ItemsSource is set for the ItemsRepeater created in the XAML file.\n VariedImageSizeRepeater.ItemsSource = filteredRecipeData;\n\n // ...\n}\n\n// ========================== Filtering, sorting, animating ========================== \npublic void FilterRecipes_FilterChanged(object sender, RoutedEventArgs e)\n{\n UpdateSortAndFilter();\n}\n\nprivate void OnSortAscClick(object sender, RoutedEventArgs e)\n{\n if (IsSortDescending == true)\n {\n IsSortDescending = false;\n UpdateSortAndFilter();\n }\n}\n\nprivate void OnSortDesClick(object sender, RoutedEventArgs e)\n{\n if (!IsSortDescending == true)\n {\n IsSortDescending = true;\n UpdateSortAndFilter();\n }\n}\n\nprivate void UpdateSortAndFilter()\n{\n // This is a Linq query that fetches all Recipes containing the ingredient \n // typed into the filter text box.\n var filteredTypes = staticRecipeData\n .Where(i =\u003E i.Ingredients.Contains(\n FilterRecipes.Text,\n StringComparison.InvariantCultureIgnoreCase));\n // After filtering, sort the collection \n var sortedFilteredTypes = IsSortDescending ?\n filteredTypes.OrderByDescending(i =\u003E i.numIngredients) :\n filteredTypes.OrderBy(i =\u003E i.numIngredients);\n // Re-initialize the collection with this newly filtered data\n filteredRecipeData.InitializeCollection(sortedFilteredTypes);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsRepeaterVirtualizedContentHeavyLayout.txt",
+ "source": "WinUIGallery/Samples/ItemsRepeater/ItemsRepeaterVirtualizedContentHeavyLayout.txt",
+ "name": "Virtualized Content Heavy Layout",
+ "xamlOmittedUnboundPrefixes": [
+ "common",
+ "l"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "itemsview",
+ "name": "ItemsView",
+ "description": "A control that presents a collection of items using various layouts.",
+ "details": "The ItemsView lets you show a collection of items using scrollable \u0026 swappable layouts.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AnnotatedScrollBar",
+ "ItemsRepeater",
+ "ListView",
+ "GridView",
+ "ScrollView"
+ ],
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "System.Collections.Generic",
+ "System.Collections.ObjectModel",
+ "System.Threading.Tasks"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "collection",
+ "items source",
+ "layout"
+ ],
+ "docs": [
+ {
+ "title": "ItemsView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemsview"
+ },
+ {
+ "title": "CollectionViewSource - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Data.CollectionViewSource"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ItemsView",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/ItemsView/ItemsViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ItemsView/ItemsViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AnnotatedScrollBar",
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#ScrollView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic ItemsView",
+ "xaml": "\u003CDataTemplate x:Key=\u0022ImageTemplate\u0022 x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CItemContainer HorizontalAlignment=\u0022Left\u0022 Width=\u0022200\u0022 Height=\u0022140\u0022 AutomationProperties.Name=\u0022{x:Bind Title}\u0022\u003E\n \u003CImage Stretch=\u0022UniformToFill\u0022 HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022 Source=\u0022{x:Bind ImageLocation}\u0022 Margin=\u00224\u0022 AutomationProperties.AccessibilityView=\u0022Raw\u0022/\u003E\n \u003C/ItemContainer\u003E\n\u003C/DataTemplate\u003E\n\n\u003CItemsView Width=\u0022220\u0022 Height=\u0022400\u0022 HorizontalAlignment=\u0022Left\u0022\n ItemTemplate=\u0022{StaticResource ImageTemplate}\u0022 IsItemInvokedEnabled=\u0022True\u0022 ItemInvoked=\u0022BasicItemsView_ItemInvoked\u0022/\u003E",
+ "code": "private void BasicItemsView_ItemInvoked(ItemsView sender, ItemsViewItemInvokedEventArgs e)\n{\n tblBasicInvokeOutput.Text = \u0022You invoked \u0022 \u002B (e.InvokedItem as CustomDataObject).Title \u002B \u0022.\u0022;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BasicItemsview.txt",
+ "source": "WinUIGallery/Samples/ItemsView/BasicItemsview.txt",
+ "name": "Basic Itemsview"
+ }
+ },
+ {
+ "header": "ItemsView with swappable layouts",
+ "xaml": "\u003CDataTemplate x:Key=\u0022LinedFlowLayoutItemTemplate\u0022 x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CItemContainer AutomationProperties.Name=\u0022{x:Bind Title}\u0022\u003E\n \u003CGrid\u003E\n \u003CImage Source=\u0022{x:Bind ImageLocation}\u0022 Stretch=\u0022UniformToFill\u0022 HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022 MinWidth=\u002270\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Vertical\u0022 Height=\u002240\u0022 VerticalAlignment=\u0022Bottom\u0022 Padding=\u00225,1,5,1\u0022 Background=\u0022{ThemeResource SystemControlBackgroundBaseMediumBrush}\u0022 Opacity=\u0022.75\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Title}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Likes}\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003CTextBlock Text=\u0022 Likes\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n \u003C/ItemContainer\u003E\n\u003C/DataTemplate\u003E\n\n\u003CItemsView Width=\u0022500\u0022 Height=\u0022400\u0022 HorizontalAlignment=\u0022Left\u0022\n ItemTemplate=\u0022{StaticResource LinedFlowLayoutItemTemplate}\u0022\u003E\n \u003CItemsView.Layout\u003E\n \u003CLinedFlowLayout ItemsStretch=\u0022Fill\u0022 LineHeight=\u0022160\u0022 LineSpacing=\u00225\u0022 MinItemSpacing=\u00225\u0022/\u003E\n \u003C/ItemsView.Layout\u003E\n\u003C/ItemsView\u003E",
+ "gallery": {
+ "snippet": "ItemsviewSwappableLayouts.txt",
+ "source": "WinUIGallery/Samples/ItemsView/ItemsviewSwappableLayouts.txt",
+ "name": "Swappable Layouts"
+ }
+ },
+ {
+ "header": "ItemsView item invocation and selection",
+ "xaml": "\u003CDataTemplate x:Key=\u0022UniformGridLayoutItemTemplate\u0022 x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CItemContainer AutomationProperties.Name=\u0022{x:Bind Title}\u0022\u003E\n \u003CGrid Width=\u0022150\u0022\u003E\n \u003CImage Source=\u0022{x:Bind ImageLocation}\u0022 Stretch=\u0022UniformToFill\u0022 HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Vertical\u0022 Height=\u002240\u0022 VerticalAlignment=\u0022Bottom\u0022 Padding=\u00225,1,5,1\u0022 Background=\u0022{ThemeResource SystemControlBackgroundBaseMediumBrush}\u0022 Opacity=\u0022.75\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Title}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Likes}\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003CTextBlock Text=\u0022 Likes\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Foreground=\u0022{ThemeResource SystemControlForegroundAltHighBrush}\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n \u003C/ItemContainer\u003E\n\u003C/DataTemplate\u003E\n\n\u003CItemsView Width=\u0022500\u0022 Height=\u0022400\u0022 HorizontalAlignment=\u0022Left\u0022\n SelectionMode=\u0022Multiple\u0022\n ItemTemplate=\u0022{StaticResource UniformGridLayoutItemTemplate}\u0022\n ItemInvoked=\u0022SwappableSelectionModesItemsView_ItemInvoked\u0022\n SelectionChanged=\u0022SwappableSelectionModesItemsView_SelectionChanged\u0022\u003E\n \u003CItemsView.Layout\u003E\n \u003CUniformGridLayout MinRowSpacing=\u00225\u0022 MinColumnSpacing=\u00225\u0022 MaximumRowsOrColumns=\u00223\u0022/\u003E\n \u003C/ItemsView.Layout\u003E\n\u003C/ItemsView\u003E",
+ "code": "private void SwappableSelectionModesItemsView_ItemInvoked(ItemsView sender, ItemsViewItemInvokedEventArgs e)\n{\n tblInvocationOutput.Text = \u0022You invoked \u0022 \u002B (e.InvokedItem as CustomDataObject).Title \u002B \u0022.\u0022;\n}\n\nprivate void SwappableSelectionModesItemsView_SelectionChanged(ItemsView sender, ItemsViewSelectionChangedEventArgs e)\n{\n tblSelectionOutput.Text = string.Format(\u0022You have selected {0} item(s).\u0022, SwappableSelectionModesItemsView.SelectedItems.Count);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ItemsviewItemInvocationSelection.txt",
+ "source": "WinUIGallery/Samples/ItemsView/ItemsviewItemInvocationSelection.txt",
+ "name": "Item Invocation Selection",
+ "xamlPlaceholdersDropped": [
+ "IsItemInvokedEnabled"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "jumplist",
+ "name": "JumpList",
+ "description": "Add custom tasks and groups to the app\u0027s taskbar jump list.",
+ "details": "Jump lists let you add custom tasks and groups to the app\u0027s right-click menu on the taskbar. Use them to provide quick access to frequently used actions or recently opened items.",
+ "apiNamespace": "Windows.UI.StartScreen",
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "System",
+ "Windows.UI.StartScreen"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "jump list",
+ "taskbar",
+ "recent",
+ "tasks"
+ ],
+ "docs": [
+ {
+ "title": "JumpList - API",
+ "uri": "https://learn.microsoft.com/uwp/api/windows.ui.startscreen.jumplist"
+ },
+ {
+ "title": "JumpListItem - API",
+ "uri": "https://learn.microsoft.com/uwp/api/windows.ui.startscreen.jumplistitem"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "JumpList",
+ "group": {
+ "id": "Shell",
+ "title": "Shell"
+ },
+ "page": "WinUIGallery/Samples/JumpList/JumpListPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/JumpList/JumpListPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "badges": [
+ "New"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Adding tasks to the jump list",
+ "code": "var jumpList = await JumpList.LoadCurrentAsync();\n\nvar task = JumpListItem.CreateWithArguments(\u0022/compose\u0022, \u0022New Message\u0022);\ntask.Description = \u0022Compose a new message\u0022;\ntask.Logo = new Uri(\u0022ms-appx:///Assets/Tiles/AppList.targetsize-48.png\u0022);\n\njumpList.Items.Add(task);\nawait jumpList.SaveAsync();",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "AddingTasksJumpList.txt",
+ "source": "WinUIGallery/Samples/JumpList/AddingTasksJumpList.txt",
+ "name": "Adding Tasks Jump List"
+ }
+ },
+ {
+ "header": "Adding items to a custom group",
+ "code": "var jumpList = await JumpList.LoadCurrentAsync();\n\nvar item = JumpListItem.CreateWithArguments(\u0022/project-alpha\u0022, \u0022Project Alpha\u0022);\nitem.GroupName = \u0022Projects\u0022;\nitem.Description = \u0022Open Project Alpha\u0022;\nitem.Logo = new Uri(\u0022ms-appx:///Assets/Tiles/AppList.targetsize-48.png\u0022);\n\njumpList.Items.Add(item);\nawait jumpList.SaveAsync();",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "JumpListAddingItemsCustomGroup.txt",
+ "source": "WinUIGallery/Samples/JumpList/JumpListAddingItemsCustomGroup.txt",
+ "name": "Adding Items Custom Group"
+ }
+ }
+ ]
+ },
+ {
+ "id": "layoutpanel",
+ "name": "LayoutPanel",
+ "description": "A panel that uses a Layout object to measure and arrange its children.",
+ "details": "Use LayoutPanel to apply a reusable Layout, including a custom NonVirtualizingLayout, to ordinary panel children. LayoutPanel also provides border, corner radius, and padding properties.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ItemsRepeater"
+ ],
+ "xmlnsImports": [
+ "xmlns:layouts=\u0022using:WinUIGallery.Layouts\u0022"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "layout panel",
+ "custom layout",
+ "non virtualizing layout",
+ "panel"
+ ],
+ "docs": [
+ {
+ "title": "LayoutPanel - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.layoutpanel"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "LayoutPanel",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/LayoutPanel/LayoutPanelPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/LayoutPanel/LayoutPanelPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ItemsRepeater"
+ ]
+ },
+ "samples": [
+ {
+ "header": "LayoutPanel lets a custom Layout arrange ordinary panel children.",
+ "xaml": "\u003CLayoutPanel\n BorderBrush=\u0022{ThemeResource CardStrokeColorDefaultBrush}\u0022\n BorderThickness=\u00221\u0022\n CornerRadius=\u00228\u0022\n Padding=\u002212\u0022\u003E\n \u003CLayoutPanel.Layout\u003E\n \u003Clayouts:FeaturedTileLayout Spacing=\u00228\u0022/\u003E\n \u003C/LayoutPanel.Layout\u003E\n\n \u003CBorder Height=\u002296\u0022\u003E\n \u003CTextBlock Text=\u0022Featured item\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002272\u0022\u003E\n \u003CTextBlock Text=\u0022Second\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002292\u0022\u003E\n \u003CTextBlock Text=\u0022Third\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002280\u0022\u003E\n \u003CTextBlock Text=\u0022Fourth\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002264\u0022\u003E\n \u003CTextBlock Text=\u0022Fifth\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002288\u0022\u003E\n \u003CTextBlock Text=\u0022Sixth\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002268\u0022\u003E\n \u003CTextBlock Text=\u0022Seventh\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002276\u0022\u003E\n \u003CTextBlock Text=\u0022Eighth\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Height=\u002296\u0022\u003E\n \u003CTextBlock Text=\u0022Ninth\u0022/\u003E\n \u003C/Border\u003E\n\u003C/LayoutPanel\u003E",
+ "code": "public partial class FeaturedTileLayout : NonVirtualizingLayout\n{\n protected override Size MeasureOverride(\n NonVirtualizingLayoutContext context,\n Size availableSize)\n {\n // Measure the first child at full width and the remaining\n // children in two columns, then return the combined extent.\n // See FeaturedTileLayout.cs in the WinUI Gallery for the\n // complete measure and arrange implementation.\n }\n\n protected override Size ArrangeOverride(\n NonVirtualizingLayoutContext context,\n Size finalSize)\n {\n // Arrange the first child across the panel. Arrange each\n // subsequent pair in equal-width columns.\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "LayoutPanelCustomLayout.txt",
+ "source": "WinUIGallery/Samples/LayoutPanel/LayoutPanelCustomLayout.txt",
+ "name": "Custom Layout"
+ }
+ }
+ ]
+ },
+ {
+ "id": "line",
+ "name": "Line",
+ "description": "Draws a straight line between two points.",
+ "details": "Draws a straight line between two points.",
+ "apiNamespace": "Microsoft.UI.Xaml.Shapes",
+ "relatedControls": [
+ "Shape"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Shape"
+ ],
+ "curatedKeywords": [
+ "stroke",
+ "draw line"
+ ],
+ "docs": [
+ {
+ "title": "Lines - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.shapes"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/previous-versions/windows/apps/hh465055(v=win.10)"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Line",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/Line/LinePage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Line/LinePage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Shape"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Shape"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Line",
+ "xaml": "\u003CLine Stroke=\u0022SteelBlue\u0022/\u003E",
+ "gallery": {
+ "snippet": "Line.txt",
+ "source": "WinUIGallery/Samples/Line/Line.txt",
+ "name": "Line",
+ "xamlPlaceholdersDropped": [
+ "Slider1",
+ "Slider2",
+ "Slider3",
+ "Slider4",
+ "Slider5"
+ ]
+ }
+ },
+ {
+ "header": "Polyline",
+ "xaml": "\u003CPolyline Stroke=\u0022Black\u0022\n Points=\u002210,100 60,40 200,40 250,100\u0022/\u003E",
+ "gallery": {
+ "snippet": "Polyline.txt",
+ "source": "WinUIGallery/Samples/Line/Polyline.txt",
+ "name": "Polyline",
+ "xamlPlaceholdersDropped": [
+ "Slider1"
+ ]
+ }
+ },
+ {
+ "header": "Path",
+ "xaml": "\u003C!-- The first segment is a cubic Bezier curve that begins at Point #1 and ends at Point #4, which is drawn by using Point #2 and 3 as the two control points. This segment is indicated by the \u0022C\u0022 command in the Data attribute string. --\u003E\n\u003C!-- The second segment begins with an absolute horizontal line command \u0022H\u0022, which specifies a line drawn from the preceding subpath endpoint (Point #4) to a new endpoint (Point #5). Because it\u0027s a horizontal line command, the value specified is an x-coordinate. --\u003E\n \n\u003CPath Stroke=\u0022DarkGoldenRod\u0022\n Data=\u0022M 10,100 C 100,25 300,250 400,75 H 200\u0022/\u003E",
+ "gallery": {
+ "snippet": "LinePath.txt",
+ "source": "WinUIGallery/Samples/Line/LinePath.txt",
+ "name": "Path",
+ "xamlPlaceholdersDropped": [
+ "Slider1"
+ ]
+ }
+ },
+ {
+ "header": "GeometryGroup",
+ "xaml": "\u003CPath Stroke=\u0022Black\u0022 StrokeThickness=\u00224\u0022 Fill=\u0022#CCCCFF\u0022\u003E\n \u003CPath.Data\u003E\n \n \u003C!-- Creates a composite shape from three geometries. --\u003E\n \u003CGeometryGroup FillRule=\u0022EvenOdd\u0022\u003E\n \u003CLineGeometry StartPoint=\u002210,10\u0022 EndPoint=\u002250,30\u0022 /\u003E\n \u003CEllipseGeometry Center=\u002240,70\u0022 /\u003E\n \u003CRectangleGeometry Rect=\u002230,55 100 30\u0022 /\u003E\n \u003C/GeometryGroup\u003E\n \u003C/Path.Data\u003E\n\u003C/Path\u003E",
+ "gallery": {
+ "snippet": "LineGeometrygroup.txt",
+ "source": "WinUIGallery/Samples/Line/LineGeometrygroup.txt",
+ "name": "Geometrygroup",
+ "xamlPlaceholdersDropped": [
+ "Slider1",
+ "Slider2"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "listview",
+ "name": "ListView",
+ "description": "A control that presents a collection of items in a vertical list.",
+ "details": "The ListView lets you show a collection of items in a list that scrolls vertically.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ItemsView",
+ "GridView",
+ "StandardUICommand",
+ "FlipView",
+ "SemanticZoom"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Navigation",
+ "System",
+ "System.Collections.Generic",
+ "System.Collections.ObjectModel",
+ "System.Linq",
+ "System.Runtime.InteropServices.WindowsRuntime",
+ "System.Threading.Tasks",
+ "Windows.ApplicationModel.DataTransfer"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector",
+ "ListViewBase"
+ ],
+ "curatedKeywords": [
+ "list",
+ "selection",
+ "collection list"
+ ],
+ "docs": [
+ {
+ "title": "ListView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.listview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/listview-and-gridview"
+ },
+ {
+ "title": "Drag and Drop - Full Sample",
+ "uri": "https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/XamlDragAndDrop"
+ },
+ {
+ "title": "CollectionViewSource - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Data.CollectionViewSource"
+ },
+ {
+ "title": "Filtering collections and lists through user input",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/listview-filtering"
+ },
+ {
+ "title": "Inverted Lists",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/inverted-lists"
+ },
+ {
+ "title": "Inverted Lists - Full Sample",
+ "uri": "https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlBottomUpList"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ListView",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/ListView/ListViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ListView/ListViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl",
+ "Selector",
+ "ListViewBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#FlipView",
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ItemsView",
+ "microsoft/WinUI-Gallery#SemanticZoom",
+ "microsoft/WinUI-Gallery#StandardUICommand"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic ListView with Simple DataTemplate",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003CListView\n x:Name=\u0022BaseExample\u0022\n ItemTemplate=\u0022{StaticResource ContactListViewTemplate}\u0022\n BorderThickness=\u00221\u0022\n BorderBrush=\u0022{ThemeResource SystemControlForegroundBaseMediumLowBrush}\u0022\n Width=\u0022350\u0022 \n Height=\u0022400\u0022\n HorizontalAlignment=\u0022Left\u0022/\u003E\n \n\u003C!-- In this example, the ListView\u0027s ItemTemplate property is bound to a data template (shown below)\ncalled ContactListViewTemplate, defined in a Page.Resources section. --\u003E\n \n\u003CDataTemplate x:Key=\u0022ContactListViewTemplate\u0022 x:DataType=\u0022local:Contact\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Name}\u0022 x:Phase=\u00221\u0022 Margin=\u00220,5,0,5\u0022/\u003E\n\u003C/DataTemplate\u003E",
+ "code": "// C# code-behind\n \n// The data template is defined to display a Contact object (class definition shown below), and the text \n// displayed is bound to the Contact object\u0027s Name attribute.\n\npublic class Contact\n{\n public string FirstName { get; private set; } = string.Empty;\n public string LastName { get; private set; } = string.Empty;\n public string Company { get; private set; } = string.Empty;\n public string Name =\u003E FirstName \u002B \u0022 \u0022 \u002B LastName;\n\n public Contact(string firstName, string lastName, string company)\n {\n FirstName = firstName;\n LastName = lastName;\n Company = company;\n } \n}\n \n// The ItemsSource for the ListView is generated by a method of the Contact class called \n// GetContactsAsync().This method pulls data from an internal data source and creates \n// Contact objects from that data. Those Contact objects are placed in a collection \n// which is returned from the GetContactsAsync() function.\n\nBaseExample.ItemsSource = await Contact.GetContactsAsync();",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "BasicListviewSimpleDatatemplate.txt",
+ "source": "WinUIGallery/Samples/ListView/BasicListviewSimpleDatatemplate.txt",
+ "name": "Basic Listview Simple Datatemplate"
+ }
+ },
+ {
+ "header": "ListView with Selection Support",
+ "xaml": "\u003C!-- To create this sample, add/change the following properties onto the code for the base example above: --\u003E\n \n\u003CListView\n ItemTemplate=\u0022{StaticResource ContactListViewTemplate}\u0022/\u003E\n \n\u003C!-- DataTemplate used: --\u003E\n\n\u003CDataTemplate x:Key=\u0022ContactListViewTemplate\u0022 x:DataType=\u0022local:Contact\u0022\u003E\n \u003CGrid\u003E\n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n \u003CColumnDefinition Width=\u0022*\u0022/\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003CEllipse x:Name=\u0022Ellipse\u0022\n Grid.RowSpan=\u00222\u0022\n Width =\u002232\u0022\n Height=\u002232\u0022\n Margin=\u00226\u0022\n VerticalAlignment=\u0022Center\u0022\n HorizontalAlignment=\u0022Center\u0022\n Fill=\u0022{ThemeResource SystemControlBackgroundBaseMediumBrush}\u0022/\u003E\n \u003CTextBlock Grid.Column=\u00221\u0022\n Text=\u0022{x:Bind Name}\u0022\n x:Phase=\u00221\u0022\n Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022\n Margin=\u002212,6,0,0\u0022/\u003E\n \u003CTextBlock Grid.Column=\u00221\u0022\n Grid.Row=\u00221\u0022\n Text=\u0022{x:Bind Company}\u0022\n x:Phase=\u00222\u0022\n Style=\u0022{ThemeResource BodyTextBlockStyle}\u0022\n Margin=\u002212,0,0,6\u0022/\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "ListviewSelectionSupport.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewSelectionSupport.txt",
+ "name": "Selection Support",
+ "xamlPlaceholdersDropped": [
+ "SelectionMode"
+ ]
+ }
+ },
+ {
+ "header": "ListViews with Drag, Drop, and Reordering Support",
+ "xaml": "\u003C!-- Full code to implement dragging and dropping between lists can be found in the \nsource code for the WinUI Gallery. --\u003E\n\n\u003C!-- The following properties should be added to the ListView definitions to build this sample. --\u003E\n\u003CListView CanDragItems=\u0022True\u0022 CanReorderItems=\u0022True\u0022 AllowDrop=\u0022True\u0022\n SelectionMode=\u0022Single\u0022 /\u003E\n \n\u003C!-- DataTemplate used is the same as the above sample. --\u003E",
+ "gallery": {
+ "snippet": "ListviewsDragDropReordering.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewsDragDropReordering.txt",
+ "name": "s Drag Drop Reordering"
+ }
+ },
+ {
+ "header": "ListView with Grouped Headers",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003C!-- ListViews with grouped items must be bound to a CollectionViewSource, as shown below.\nThis CollectionViewSource is defined in the XAML below, but is bound to an ItemsSource in the C#\ncode-behind. See the C# code below for more details on how to create/bind to a grouped list. --\u003E\n\n\u003CCollectionViewSource x:Name=\u0022ContactsCVS\u0022 IsSourceGrouped=\u0022True\u0022/\u003E\n \n\u003CListView ItemsSource=\u0022{x:Bind ContactsCVS.View, Mode=OneWay}\u0022\u003E\n \u003CListView.ItemsPanel\u003E\n \u003CItemsPanelTemplate\u003E\n \u003CItemsStackPanel AreStickyGroupHeadersEnabled=\u0022False\u0022/\u003E\n \u003C/ItemsPanelTemplate\u003E\n \u003C/ListView.ItemsPanel\u003E\n \u003CListView.GroupStyle\u003E\n \u003CGroupStyle \u003E\n \u003CGroupStyle.HeaderTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022local:GroupInfoList\u0022\u003E\n \u003CBorder AutomationProperties.AccessibilityView=\u0022Raw\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Key}\u0022 Style=\u0022{ThemeResource TitleTextBlockStyle}\u0022 AutomationProperties.AccessibilityView=\u0022Raw\u0022/\u003E\n \u003C/Border\u003E\n \u003C/DataTemplate\u003E\n \u003C/GroupStyle.HeaderTemplate\u003E\n \u003C/GroupStyle\u003E\n \u003C/ListView.GroupStyle\u003E\n\u003C/ListView\u003E\n \n\u003C!-- Data template used is same as above examples. --\u003E",
+ "code": "// C# Code\n\n// To create a collection of grouped items, create a query that groups\n// an existing list, or returns a grouped collection from a database.\n// The following method is used to create the ItemsSource for our CollectionViewSource:\n\npublic static async Task\u003CObservableCollection\u003CGroupInfoList\u003E\u003E GetContactsGroupedAsync()\n{\n // Grab Contact objects from pre-existing list (list is returned from function GetContactsAsync())\n var query = from item in await GetContactsAsync()\n\n // Group the items returned from the query, sort and select the ones you want to keep\n group item by item.LastName.Substring(0, 1).ToUpper() into g\n orderby g.Key\n\n // GroupInfoList is a simple custom class that has an IEnumerable type attribute, and\n // a key attribute. The IGrouping-typed variable g now holds the Contact objects, \n // and these objects will be used to create a new GroupInfoList object.\n select new GroupInfoList(g) { Key = g.Key };\n \n return new ObservableCollection\u003CGroupInfoList\u003E(query);\n}\n\n// GroupInfoList class definition:\npublic class GroupInfoList : List\u003Cobject\u003E\n{\n public GroupInfoList(IEnumerable\u003Cobject\u003E items) : base(items)\n {\n }\n\n public object Key { get; set; }\n\n public override string ToString()\n {\n return \u0022Group \u0022 \u002B Key.ToString();\n }\n}\n\n// Contact class definition:\npublic class Contact\n{\n public string FirstName { get; private set; } = string.Empty;\n public string LastName { get; private set; } = string.Empty;\n public string Company { get; private set; } = string.Empty;\n public string Name =\u003E FirstName \u002B \u0022 \u0022 \u002B LastName;\n\n public Contact(string firstName, string lastName, string company)\n {\n FirstName = firstName;\n LastName = lastName;\n Company = company;\n }\n\n // ... Methods ...\n}\n\nContactsCVS.Source = await Contact.GetContactsGroupedAsync();",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "ListviewGroupedHeaders.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewGroupedHeaders.txt",
+ "name": "Grouped Headers"
+ }
+ },
+ {
+ "header": "ListView with filtering",
+ "xaml": "\u003C!-- XAML Code --\u003E\n\n\u003C!-- The ListView\u0027s ItemsSource is an ObservableCollection\u003CContact\u003E that is defined and bound\nin the code-behind, called contactsFiltered. This ListView uses the same DataTemplate as the\nsamples above it, called ContactListViewTemplate - you can see its definition above. --\u003E\n\n\u003CListView \n x:Name=\u0022FilteredListView\u0022\n ItemTemplate=\u0022{StaticResource ContactListViewTemplate}\u0022\n SelectionMode=\u0022Single\u0022\n ShowsScrollingPlaceholders=\u0022True\u0022\n Height=\u0022400\u0022\n Width=\u0022400\u0022\n BorderThickness=\u00221\u0022\n BorderBrush=\u0022{ThemeResource SystemControlForegroundBaseMediumLowBrush}\u0022/\u003E\n\n\u003C!-- The textboxes used for filtering are shown below: --\u003E\n\u003CStackPanel Width=\u0022200\u0022\u003E\n \u003CTextBlock Margin=\u00228,8,8,4\u0022 Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022\u003EFilter by...\u003C/TextBlock\u003E\n \u003CTextBox x:Name=\u0022FilterByFirstName\u0022 Width=\u0022150\u0022 Header=\u0022First name\u0022 Margin=\u00228\u0022\n\t HorizontalAlignment=\u0022Left\u0022 TextChanged=\u0022OnFilterChanged\u0022/\u003E\n \u003CTextBox x:Name=\u0022FilterByLastName\u0022 Width=\u0022150\u0022 Header=\u0022Last name\u0022 Margin=\u00228\u0022\n\t HorizontalAlignment=\u0022Left\u0022 TextChanged=\u0022OnFilterChanged\u0022/\u003E\n \u003CTextBox x:Name=\u0022FilterByCompany\u0022 Width=\u0022150\u0022 Header=\u0022Company\u0022 Margin=\u00228\u0022 \n\t HorizontalAlignment=\u0022Left\u0022 TextChanged=\u0022OnFilterChanged\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "code": "// C# Code\n\n// Make sure to add this to your declarations at the top for the filtering method:\nusing System.Linq;\n// ...\n\n// Define an ObservableCollection\u003CContact\u003E object to serve as the ListView\u0027s\n// ItemsSource. This collection will get updated after the filters are used:\nObservableCollection\u003CContact\u003E contactsFiltered = new ObservableCollection\u003CContact\u003E();\n\n/* Populate contactsFiltered with all contact objects (in this case, contacts holds\nall of our Contact objects so we copy them into contactsFiltered). Set this newly populated\ncollection as the ItemsSource for the ListView. */\ncontactsFiltered = new ObservableCollection\u003CContact\u003E(allContacts);\nFilteredListView.ItemsSource = contactsFiltered;\n\n\n// Whenever text changes in any of the filtering text boxes, the following function is called:\nprivate void OnFilterChanged(object sender, TextChangedEventArgs args)\n{\n // This is a Linq query that selects only items that return True after being passed through\n // the Filter function, and adds all of those selected items to filtered.\n var filtered = allContacts.Where(contact =\u003E Filter(contact));\n Remove_NonMatching(filtered);\n AddBack_Contacts(filtered);\n}\n\n// The following functions are called inside OnFilterChanged:\n\n/* When the text in any filter is changed, perform a check on each item in the original \ncontact list to see if the item should be displayed, taking into account all three of the\nfilters currently applied. If the item passes all three checks for all three filters, \nthe function returns true and the item is added to the filtered list above. */\nprivate bool Filter(Contact contact)\n{\n return contact.FirstName.Contains(FilterByFirstName.Text, StringComparison.InvariantCultureIgnoreCase) \u0026\u0026\n contact.LastName.Contains(FilterByLastName.Text, StringComparison.InvariantCultureIgnoreCase) \u0026\u0026\n contact.Company.Contains(FilterByCompany.Text, StringComparison.InvariantCultureIgnoreCase);\n}\n\n/* These functions go through the current list being displayed (contactsFiltered), and remove\nany items not in the filtered collection (any items that don\u0027t belong), or add back any items \nfrom the original allContacts list that are now supposed to be displayed (i.e. when backspace is hit). */\n\nprivate void Remove_NonMatching(IEnumerable\u003CContact\u003E filteredData)\n{\n for (int i = contactsFiltered.Count - 1; i \u003E= 0; i--)\n {\n var item = contactsFiltered[i];\n // If contact is not in the filtered argument list, remove it from the ListView\u0027s source.\n if (!filteredData.Contains(item))\n {\n contactsFiltered.Remove(item);\n }\n }\n}\n\nprivate void AddBack_Contacts(IEnumerable\u003CContact\u003E filteredData)\n{\n foreach (var item in filteredData)\n {\n // If item in filtered list is not currently in ListView\u0027s source collection, add it back in\n if (!contactsFiltered.Contains(item))\n {\n contactsFiltered.Add(item);\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ListviewFiltering.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewFiltering.txt",
+ "name": "Filtering"
+ }
+ },
+ {
+ "header": "ListView for Messaging or Data Logging",
+ "xaml": "\u003CListView x:Name=\u0022InvertedListView\u0022\n ItemTemplate=\u0022{StaticResource MessageViewTemplate}\u0022\u003E\n \n \u003C!-- The ItemsStackPanel must be edited to update the following two properties --\u003E\n \u003C!-- These properties allow the list to grow from the bottom --\u003E\n \u003CListView.ItemsPanel\u003E\n \u003CItemsPanelTemplate\u003E\n \u003CItemsStackPanel ItemsUpdatingScrollMode=\u0022KeepLastItemInView\u0022 \n VerticalAlignment=\u0022Bottom\u0022/\u003E\n \u003C/ItemsPanelTemplate\u003E\n \u003C/ListView.ItemsPanel\u003E\n\n \u003C!-- This setter property is created so ListViewItems correctly align to the left or right. --\u003E\n \u003CListView.ItemContainerStyle\u003E\n \u003CStyle TargetType=\u0022ListViewItem\u0022\u003E\n \u003CSetter Property=\u0022HorizontalContentAlignment\u0022 Value=\u0022Stretch\u0022/\u003E\n \u003C/Style\u003E\n \u003C/ListView.ItemContainerStyle\u003E\n\u003C/ListView\u003E\n\n\u003C!-- Data template used: --\u003E\n\u003C!-- The data template is bound to a custom DataType called Message. --\u003E\n\u003C!-- Each Message object has a color and alignment assigned to it based on whether it was \nsent or received, and those values are bound in the DataTemplate.--\u003E\n\u003CDataTemplate x:Key=\u0022MessageViewTemplate\u0022 x:DataType=\u0022local:Message\u0022\u003E\n \u003CGrid Height=\u0022Auto\u0022 Margin=\u00224\u0022 HorizontalAlignment=\u0022{x:Bind MsgAlignment}\u0022\u003E\n \u003CStackPanel MinHeight=\u002275\u0022 Width=\u0022350\u0022 Padding=\u002210, 0, 0, 10\u0022 Background=\u0022{ThemeResource SystemColorHighlightColor}\u0022 CornerRadius=\u0022{StaticResource ControlCornerRadius}\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind MsgText}\u0022 Padding=\u00220, 10, 0, 0\u0022 FontSize=\u002220\u0022 Foreground=\u0022{ThemeResource SystemColorHighlightTextColor}\u0022/\u003E\n \u003CTextBlock Text=\u0022{x:Bind MsgDateTime}\u0022 Padding=\u00220, 0, 0, 10\u0022 FontSize=\u002215\u0022 Foreground=\u0022{ThemeResource SystemColorHighlightTextColor}\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "ListviewMessagingDataLogging.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewMessagingDataLogging.txt",
+ "name": "Messaging Data Logging"
+ }
+ },
+ {
+ "header": "ListView with Images",
+ "xaml": "\u003CListView x:Name=\u0022Control4\u0022\n Height=\u0022400\u0022\n MinWidth=\u0022550\u0022\n BorderThickness=\u00221\u0022\n BorderBrush=\u0022{ThemeResource ControlStrongStrokeColorDefaultBrush}\u0022\u003E\n \n\u003C!-- Data Template Used: --\u003E\n\u003C!-- The data template is bound to a custom-created data type called CustomDataObject. --\u003E\n\u003C!-- The full code for the class can be found in this page\u0027s source code, but its attributes are referenced/bound below. --\u003E\n\n\u003CListView.ItemTemplate\u003E\n\u003CDataTemplate x:DataType=\u0022local:CustomDataObject\u0022\u003E\n \u003CGrid Margin=\u00220,12,0,12\u0022 AutomationProperties.Name=\u0022{x:Bind Title}\u0022\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022Auto\u0022 MinWidth=\u0022150\u0022/\u003E\n \u003CColumnDefinition Width=\u0022*\u0022 /\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003CImage Source=\u0022{x:Bind ImageLocation}\u0022 MaxHeight=\u0022100\u0022 Stretch=\u0022Fill\u0022/\u003E\n\n \u003CStackPanel Margin=\u002212,0,0,0\u0022 Grid.Column=\u00221\u0022 \u003E\n \u003CTextBlock Text=\u0022{x:Bind Title}\u0022 FontSize=\u002214\u0022 FontWeight=\u0022SemiBold\u0022 Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022\n HorizontalAlignment=\u0022Left\u0022 Margin=\u00220,0,0,6\u0022 LineHeight=\u002220\u0022/\u003E\n \u003CTextBlock Text=\u0022{x:Bind Description}\u0022 FontFamily=\u0022Segoe UI\u0022 FontWeight=\u0022Normal\u0022 Style=\u0022{ThemeResource BodyTextBlockStyle}\u0022\n TextTrimming=\u0022CharacterEllipsis\u0022 Width=\u0022350\u0022 MaxLines=\u00221\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind Views}\u0022 HorizontalAlignment=\u0022Left\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Margin=\u00220,0,0,0\u0022/\u003E\n \u003CTextBlock Text=\u0022 Views \u0022 HorizontalAlignment=\u0022Left\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022/\u003E\n \u003CTextBlock Text=\u0022 \u00B7 \u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 \n HorizontalAlignment=\u0022Left\u0022/\u003E\n \u003CTextBlock Text=\u0022{x:Bind Likes}\u0022 HorizontalAlignment=\u0022Left\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022 Margin=\u00225,0,0,0\u0022/\u003E\n \u003CTextBlock Text=\u0022 Likes\u0022 HorizontalAlignment=\u0022Left\u0022 Style=\u0022{ThemeResource CaptionTextBlockStyle}\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n \u003C/Grid\u003E\n\u003C/DataTemplate\u003E\n\u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "ListviewImages.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewImages.txt",
+ "name": "Images"
+ }
+ },
+ {
+ "header": "ListView with context menus",
+ "xaml": "\u003CListView\n ItemsSource=\u0022{x:Bind contacts, Mode=OneWay}\u0022\n SelectionMode=\u0022Single\u0022\n ShowsScrollingPlaceholders=\u0022True\u0022\n Height=\u0022400\u0022\n Width=\u0022400\u0022\n BorderThickness=\u00221\u0022\n BorderBrush=\u0022{ThemeResource ControlStrongStrokeColorDefaultBrush}\u0022\n HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022local:Contact\u0022\u003E\n \u003CGrid\u003E\n \u003CGrid.ContextFlyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022Delete\u0022 Click=\u0022ContactDeleteMenuItem_Click\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Grid.ContextFlyout\u003E\n \n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022Auto\u0022/\u003E\n \u003CColumnDefinition Width=\u0022*\u0022/\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003CEllipse x:Name=\u0022Ellipse\u0022\n Grid.RowSpan=\u00222\u0022\n Width =\u002232\u0022\n Height=\u002232\u0022\n Margin=\u00226\u0022\n VerticalAlignment=\u0022Center\u0022\n HorizontalAlignment=\u0022Center\u0022\n Fill=\u0022{ThemeResource ControlStrongFillColorDefaultBrush}\u0022/\u003E\n \u003CTextBlock Grid.Column=\u00221\u0022\n Text=\u0022{x:Bind Name}\u0022\n x:Phase=\u00221\u0022\n Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022\n Margin=\u002212,6,0,0\u0022/\u003E\n \u003CTextBlock Grid.Column=\u00221\u0022\n Grid.Row=\u00221\u0022\n Text=\u0022{x:Bind Company}\u0022\n x:Phase=\u00222\u0022\n Style=\u0022{ThemeResource BodyTextBlockStyle}\u0022\n Margin=\u002212,0,0,6\u0022/\u003E\n \u003C/Grid\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E",
+ "code": "ObservableCollection\u003CContact\u003E contacts = new ObservableCollection\u003CContact\u003E();\n\nprivate void ContactDeleteMenuItem_Click(object sender, RoutedEventArgs e)\n{\n var item = (sender as FrameworkElement).DataContext;\n var contact = item as Contact;\n contacts.Remove(contact);\n}",
+ "language": "csharp",
+ "xmlnsImports": [
+ "xmlns:local=\u0022using:WinUIGallery.ControlPages\u0022"
+ ],
+ "gallery": {
+ "snippet": "ListviewContextMenus.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewContextMenus.txt",
+ "name": "Context Menus"
+ }
+ },
+ {
+ "header": "Save and restore the scroll position using ListViewPersistenceHelper.",
+ "xaml": "\u003CListView x:Name=\u0022RestoreScrollListView\u0022\n Height=\u0022220\u0022 Width=\u0022400\u0022 HorizontalAlignment=\u0022Left\u0022\n BorderThickness=\u00221\u0022 BorderBrush=\u0022{ThemeResource ControlStrongStrokeColorDefaultBrush}\u0022\n ItemsSource=\u0022{x:Bind contacts5}\u0022\u003E\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022x:String\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind}\u0022 Margin=\u00220,8,0,8\u0022/\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E",
+ "code": "// Persisted scroll position string. In a real app, store this somewhere that survives\n// the lifetime of the page (e.g. a static field, view-model, or app state) so it is\n// available after navigating away and back.\nprivate string _persistedPosition = string.Empty;\n\nprivate void SavePositionButton_Click(object sender, RoutedEventArgs e)\n{\n // GetRelativeScrollPosition returns an opaque string that identifies the\n // item currently at the top of the viewport plus its pixel offset.\n _persistedPosition = ListViewPersistenceHelper.GetRelativeScrollPosition(\n RestoreScrollListView,\n item =\u003E item as string ?? string.Empty);\n\n RestorePositionButton.IsEnabled = true;\n}\n\nprivate async void RestorePositionButton_Click(object sender, RoutedEventArgs e)\n{\n if (string.IsNullOrEmpty(_persistedPosition))\n {\n return;\n }\n\n // SetRelativeScrollPositionAsync scrolls the ListView back to the item identified\n // by the saved string. The callback resolves a key back to its data item.\n await ListViewPersistenceHelper.SetRelativeScrollPositionAsync(\n RestoreScrollListView,\n _persistedPosition,\n key =\u003E Task.FromResult\u003Cobject?\u003E(contacts5.FirstOrDefault(c =\u003E c == key))!.AsAsyncOperation()!);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ListviewRestoreScrollPosition.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewRestoreScrollPosition.txt",
+ "name": "Restore Scroll Position"
+ }
+ },
+ {
+ "header": "Scroll a ListView programmatically with ScrollIntoView.",
+ "xaml": "\u003CListView x:Name=\u0022ScrollIntoViewListView\u0022\n Height=\u0022220\u0022 Width=\u0022400\u0022 HorizontalAlignment=\u0022Left\u0022\n BorderThickness=\u00221\u0022 BorderBrush=\u0022{ThemeResource ControlStrongStrokeColorDefaultBrush}\u0022\n ItemsSource=\u0022{x:Bind contacts6}\u0022\u003E\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022x:String\u0022\u003E\n \u003CTextBlock Text=\u0022{x:Bind}\u0022 Margin=\u00220,8,0,8\u0022/\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E",
+ "code": "private void ScrollIntoViewButton_Click(object sender, RoutedEventArgs e)\n{\n int index = (int)ScrollIndexNumberBox.Value;\n if (index \u003C 0 || index \u003E= ScrollIntoViewListView.Items.Count)\n {\n return;\n }\n\n var alignment = ScrollAlignmentComboBox.SelectedIndex == 1\n ? ScrollIntoViewAlignment.Leading\n : ScrollIntoViewAlignment.Default;\n\n ScrollIntoViewListView.ScrollIntoView(ScrollIntoViewListView.Items[index], alignment);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ListviewScrollIntoView.txt",
+ "source": "WinUIGallery/Samples/ListView/ListviewScrollIntoView.txt",
+ "name": "Scroll Into View"
+ }
+ }
+ ]
+ },
+ {
+ "id": "mapcontrol",
+ "name": "MapControl",
+ "description": "Displays a symbolic map of the Earth.",
+ "details": "Displays a symbolic map of the Earth",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "System.Collections.Generic",
+ "Windows.Devices.Geolocation"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "maps",
+ "geography",
+ "location"
+ ],
+ "docs": [
+ {
+ "title": "MapControl - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.mapcontrol"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "MapControl",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/MapControl/MapControlPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/MapControl/MapControlPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Showing a pin on the map",
+ "xaml": "\u003CMapControl x:Name=\u0022map1\u0022 MapServiceToken=\u0022MapServiceToken\u0022 Height=\u0022600\u0022/\u003E",
+ "code": "BasicGeoposition centerPosition = new BasicGeoposition { Latitude = 0, Longitude = 0 };\nGeopoint centerPoint = new Geopoint(centerPosition);\n\nmap1.Center = centerPoint;\nmap1.ZoomLevel = 1;\n\nvar myLandmarks = new List\u003CMapElement\u003E();\nBasicGeoposition position = new BasicGeoposition { Latitude = -30.034647, Longitude = -51.217659 };\nGeopoint point = new Geopoint(position);\n\nvar icon = new MapIcon\n{\n Location = point,\n};\n\nmyLandmarks.Add(icon);\n\nvar LandmarksLayer = new MapElementsLayer\n{\n MapElements = myLandmarks\n};\n\nmap1.Layers.Add(LandmarksLayer);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "MapControlShowingPinMap.txt",
+ "source": "WinUIGallery/Samples/MapControl/MapControlShowingPinMap.txt",
+ "name": "Showing Pin Map"
+ }
+ }
+ ]
+ },
+ {
+ "id": "mediaplayerelement",
+ "name": "MediaPlayerElement",
+ "description": "A control to display video and image content.",
+ "details": "You can use a MediaPlayerElement control to playback videos and show images. You can show transport controls or make the video autoplay.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Image",
+ "Capture Element / Camera Preview"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Navigation",
+ "Microsoft.Windows.Storage.Pickers",
+ "System",
+ "Windows.Media.Core",
+ "Windows.Storage"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "video",
+ "media player",
+ "audio",
+ "playback"
+ ],
+ "docs": [
+ {
+ "title": "MediaPlayerElement - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.MediaPlayerElement"
+ },
+ {
+ "title": "Media Playback",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/media-playback"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "MediaPlayerElement",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/MediaPlayerElement/MediaPlayerElementPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/MediaPlayerElement/MediaPlayerElementPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CaptureElementPreview",
+ "microsoft/WinUI-Gallery#Image"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A MediaPlayerElement with transport controls.",
+ "xaml": "\u003CMediaPlayerElement Source=\u0022/Assets/SampleMedia/ladybug.wmv\u0022\n MaxWidth=\u0022400\u0022\n AutoPlay=\u0022False\u0022\n AreTransportControlsEnabled=\u0022True\u0022 /\u003E",
+ "code": "private async void OpenFileButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)\n{\n var picker = new FileOpenPicker((sender as Button).XamlRoot.ContentIslandEnvironment.AppWindowId);\n var file = await picker.PickSingleFileAsync();\n if (file == null)\n return;\n\n var mediaSource = MediaSource.CreateFromStorageFile(await StorageFile.GetFileFromPathAsync(file.Path));\n Player1.Source = mediaSource;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "MediaplayerelementTransportControls.txt",
+ "source": "WinUIGallery/Samples/MediaPlayerElement/MediaplayerelementTransportControls.txt",
+ "name": "Transport Controls"
+ }
+ },
+ {
+ "header": "A MediaPlayerElement that autoplays the video.",
+ "xaml": "\u003CMediaPlayerElement Source=\u0022Assets/SampleMedia/fishes.wmv\u0022\n MaxWidth=\u0022400\u0022\n AutoPlay=\u0022True\u0022 /\u003E",
+ "gallery": {
+ "snippet": "MediaplayerelementAutoplaysVideo.txt",
+ "source": "WinUIGallery/Samples/MediaPlayerElement/MediaplayerelementAutoplaysVideo.txt",
+ "name": "Autoplays Video"
+ }
+ }
+ ]
+ },
+ {
+ "id": "menubar",
+ "name": "MenuBar",
+ "description": "A classic menu, allowing the display of MenuItems containing MenuFlyoutItems.",
+ "details": "The Menubar simplifies the creation of basic applications by providing a set of menus at the top of the app or window.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "CommandBar",
+ "MenuFlyout",
+ "StandardUICommand",
+ "XamlUICommand"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "MenuBarItem",
+ "application menu"
+ ],
+ "docs": [
+ {
+ "title": "MenuBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.MenuBar"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/menus"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "MenuBar",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/MenuBar/MenuBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/MenuBar/MenuBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#MenuFlyout",
+ "microsoft/WinUI-Gallery#StandardUICommand",
+ "microsoft/WinUI-Gallery#XamlUICommand"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple MenuBar",
+ "xaml": "\u003CMenuBar\u003E\n \u003CMenuBarItem Title=\u0022File\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022New\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Open...\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Save\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Exit\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Edit\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Undo\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Cut\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Paste\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Help\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022About\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\u003C/MenuBar\u003E",
+ "gallery": {
+ "snippet": "SimpleMenubar.txt",
+ "source": "WinUIGallery/Samples/MenuBar/SimpleMenubar.txt",
+ "name": "Simple Menubar"
+ }
+ },
+ {
+ "header": "MenuBar with keyboard accelerators",
+ "xaml": "\u003CMenuBar\u003E\n \u003CMenuBarItem Title=\u0022File\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022New\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022N\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Open...\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022O\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Save\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022S\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Exit\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022E\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Edit\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Undo\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022Z\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Cut\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022X\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022C\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Paste\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022V\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Help\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022About\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Modifiers=\u0022Control\u0022 Key=\u0022I\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003C/MenuBarItem\u003E\n\u003C/MenuBar\u003E",
+ "gallery": {
+ "snippet": "MenubarKeyboardAccelerators.txt",
+ "source": "WinUIGallery/Samples/MenuBar/MenubarKeyboardAccelerators.txt",
+ "name": "Keyboard Accelerators"
+ }
+ },
+ {
+ "header": "MenuBar with submenus, separators, and radio items",
+ "xaml": "\u003CMenuBar\u003E\n \u003CMenuBarItem Title=\u0022File\u0022\u003E\n \u003CMenuFlyoutSubItem Text=\u0022New\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Plain Text Document\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Rich Text Document\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Other Formats...\u0022/\u003E\n \u003C/MenuFlyoutSubItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Open...\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Save\u0022/\u003E\n \u003CMenuFlyoutSeparator /\u003E\n \u003CMenuFlyoutItem Text=\u0022Exit\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022Edit\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Undo\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Cut\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Paste\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\n \u003CMenuBarItem Title=\u0022View\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Output\u0022/\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Landscape\u0022 GroupName=\u0022OrientationGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Portrait\u0022 GroupName=\u0022OrientationGroup\u0022 IsChecked=\u0022True\u0022/\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Small icons\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Medium icons\u0022 IsChecked=\u0022True\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Large icons\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003C/MenuBarItem\u003E\n \n \u003CMenuBarItem Title=\u0022Help\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022About\u0022/\u003E\n \u003C/MenuBarItem\u003E\n\u003C/MenuBar\u003E",
+ "gallery": {
+ "snippet": "MenubarSubmenusSeparatorsRadio.txt",
+ "source": "WinUIGallery/Samples/MenuBar/MenubarSubmenusSeparatorsRadio.txt",
+ "name": "Submenus Separators Radio"
+ }
+ }
+ ]
+ },
+ {
+ "id": "menuflyout",
+ "name": "MenuFlyout",
+ "description": "Shows a contextual list of simple commands or options.",
+ "details": "A MenuFlyout displays lightweight UI that is light dismissed by clicking or tapping off of it. Use it to let the user choose from a contextual list of simple commands or options.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Flyout",
+ "ContentDialog",
+ "Button",
+ "AppBarButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "curatedKeywords": [
+ "context menu",
+ "right click menu",
+ "MenuFlyoutItem",
+ "dropdown menu"
+ ],
+ "docs": [
+ {
+ "title": "MenuFlyout - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.menuflyout"
+ },
+ {
+ "title": "MenuFlyoutItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.menuflyoutitem"
+ },
+ {
+ "title": "MenuFlyoutSubItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.menuflyoutsubitem"
+ },
+ {
+ "title": "MenuFlyoutSeparator - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.menuflyoutseparator"
+ },
+ {
+ "title": "ToggleMenuFlyoutItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.togglemenuflyoutitem"
+ },
+ {
+ "title": "RadioMenuFlyoutItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.radiomenuflyoutitem"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/menus"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "MenuFlyout",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/MenuFlyout/MenuFlyoutPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/MenuFlyout/MenuFlyoutPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "FlyoutBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#ContentDialog",
+ "microsoft/WinUI-Gallery#Flyout"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An AppBarButton with a MenuFlyout.",
+ "xaml": "\u003CAppBarButton Icon=\u0022Sort\u0022 IsCompact=\u0022True\u0022 ToolTipService.ToolTip=\u0022Sort\u0022 AutomationProperties.Name=\u0022Sort\u0022\u003E\n \u003CAppBarButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022By rating\u0022 Click=\u0022MenuFlyoutItem_Click\u0022 Tag=\u0022rating\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022By match\u0022 Click=\u0022MenuFlyoutItem_Click\u0022 Tag=\u0022match\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022By distance\u0022 Click=\u0022MenuFlyoutItem_Click\u0022 Tag=\u0022distance\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/AppBarButton.Flyout\u003E\n\u003C/AppBarButton\u003E",
+ "gallery": {
+ "snippet": "AppbarbuttonMenuflyout.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/AppbarbuttonMenuflyout.txt",
+ "name": "Appbarbutton Menuflyout"
+ }
+ },
+ {
+ "header": "A MenuFlyout with ToggleMenuFlyoutItems and MenuFlyoutSeparator.",
+ "xaml": "\u003CButton Content=\u0022Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022Reset\u0022/\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CToggleMenuFlyoutItem Text=\u0022Repeat\u0022 IsChecked=\u0022True\u0022/\u003E\n \u003CToggleMenuFlyoutItem Text=\u0022Shuffle\u0022 IsChecked=\u0022True\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutTogglemenuflyoutitemsMenuflyoutseparator.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutTogglemenuflyoutitemsMenuflyoutseparator.txt",
+ "name": "Togglemenuflyoutitems Menuflyoutseparator"
+ }
+ },
+ {
+ "header": "A MenuFlyout with cascading menus.",
+ "xaml": "\u003CButton Content=\u0022File Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022Open\u0022/\u003E\n \u003CMenuFlyoutSubItem Text=\u0022Send to\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Bluetooth\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Desktop (shortcut)\u0022 /\u003E\n \u003CMenuFlyoutSubItem Text=\u0022Compressed file\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Compress and email\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Compress to .7z\u0022 /\u003E\n \u003CMenuFlyoutItem Text=\u0022Compress to .zip\u0022 /\u003E\n \u003C/MenuFlyoutSubItem\u003E\n \u003C/MenuFlyoutSubItem\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutCascadingMenus.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutCascadingMenus.txt",
+ "name": "Cascading Menus"
+ }
+ },
+ {
+ "header": "A MenuFlyout with SplitMenuFlyoutItems.",
+ "xaml": "\u003CButton Content=\u0022File Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CSplitMenuFlyoutItem Text=\u0022Save\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022\u003E\n \u003CSplitMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE74E;\u0022/\u003E\n \u003C/SplitMenuFlyoutItem.Icon\u003E\n \u003CMenuFlyoutItem Text=\u0022Save as .docx\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Save as .pdf\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Save as .txt\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022/\u003E\n \u003C/SplitMenuFlyoutItem\u003E\n \u003CSplitMenuFlyoutItem Text=\u0022Share\u0022 Icon=\u0022Share\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022\u003E\n \u003CMenuFlyoutItem Text=\u0022Share via email\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Share via link\u0022 Click=\u0022SplitMenuFlyoutItem_Click\u0022/\u003E\n \u003C/SplitMenuFlyoutItem\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutSplitmenuflyoutitems.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutSplitmenuflyoutitems.txt",
+ "name": "Splitmenuflyoutitems"
+ }
+ },
+ {
+ "header": "A MenuFlyout with icons.",
+ "xaml": "\u003CButton Content=\u0022Edit Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022Share\u0022\u003E\n \u003CMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE72D;\u0022/\u003E\n \u003C/MenuFlyoutItem.Icon\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022 Icon=\u0022Copy\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Delete\u0022 Icon=\u0022Delete\u0022/\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CMenuFlyoutItem Text=\u0022Rename\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Select\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutIcons.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutIcons.txt",
+ "name": "Icons"
+ }
+ },
+ {
+ "header": "A MenuFlyout with icons and Keyboard Accelerators.",
+ "xaml": "\u003CButton Content=\u0022Edit Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CMenuFlyoutItem Text=\u0022Share\u0022\u003E\n \u003CMenuFlyoutItem.Icon\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE72D;\u0022/\u003E\n \u003C/MenuFlyoutItem.Icon\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Key=\u0022S\u0022 Modifiers=\u0022Control\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Copy\u0022 Icon=\u0022Copy\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Key=\u0022C\u0022 Modifiers=\u0022Control\u0022/\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutItem Text=\u0022Delete\u0022 Icon=\u0022Delete\u0022\u003E\n \u003CMenuFlyoutItem.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Key=\u0022Delete\u0022 /\u003E\n \u003C/MenuFlyoutItem.KeyboardAccelerators\u003E\n \u003C/MenuFlyoutItem\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CMenuFlyoutItem Text=\u0022Rename\u0022/\u003E\n \u003CMenuFlyoutItem Text=\u0022Select\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutIconsKeyboardAccelerators.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutIconsKeyboardAccelerators.txt",
+ "name": "Icons Keyboard Accelerators"
+ }
+ },
+ {
+ "header": "A MenuFlyout with RadioMenuFlyoutItems",
+ "xaml": "\u003CButton Content=\u0022Options\u0022\u003E\n \u003CButton.Flyout\u003E\n \u003CMenuFlyout\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Landscape\u0022 GroupName=\u0022OrientationGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Portrait\u0022 GroupName=\u0022OrientationGroup\u0022 IsChecked=\u0022True\u0022/\u003E\n \u003CMenuFlyoutSeparator/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Small icons\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Medium icons\u0022 IsChecked=\u0022True\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003CRadioMenuFlyoutItem Text=\u0022Large icons\u0022 GroupName=\u0022SizeGroup\u0022/\u003E\n \u003C/MenuFlyout\u003E\n \u003C/Button.Flyout\u003E\n\u003C/Button\u003E",
+ "gallery": {
+ "snippet": "MenuflyoutRadiomenuflyoutitems.txt",
+ "source": "WinUIGallery/Samples/MenuFlyout/MenuflyoutRadiomenuflyoutitems.txt",
+ "name": "Radiomenuflyoutitems"
+ }
+ }
+ ]
+ },
+ {
+ "id": "navigationview",
+ "name": "NavigationView",
+ "description": "Common vertical layout for top-level areas of your app via a collapsible navigation menu.",
+ "details": "The NavigationView control provides a common vertical layout for top-level areas of your app via a collapsible navigation menu.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "SplitView",
+ "Pivot"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Automation",
+ "Microsoft.UI.Xaml.Controls",
+ "System",
+ "System.Collections.ObjectModel",
+ "System.Diagnostics",
+ "System.Linq",
+ "Windows.System"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "hamburger menu",
+ "side nav",
+ "nav pane"
+ ],
+ "docs": [
+ {
+ "title": "NavigationView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.NavigationView"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/navigationview"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "NavigationView",
+ "group": {
+ "id": "Navigation",
+ "title": "Navigation"
+ },
+ "page": "WinUIGallery/Samples/NavigationView/NavigationViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/NavigationView/NavigationViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Pivot",
+ "microsoft/WinUI-Gallery#SplitView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "NavigationView with default PaneDisplayMode",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Icon=\u0022Play\u0022 Content=\u0022Menu Item1\u0022 Tag=\u0022SamplePage1\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Save\u0022 Content=\u0022Menu Item2\u0022 Tag=\u0022SamplePage2\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Refresh\u0022 Content=\u0022Menu Item3\u0022 Tag=\u0022SamplePage3\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Download\u0022 Content=\u0022Menu Item4\u0022 Tag=\u0022SamplePage4\u0022 /\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame\u0022/\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "NavigationviewDefaultPanedisplaymode.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationviewDefaultPanedisplaymode.txt",
+ "name": "Default Panedisplaymode"
+ }
+ },
+ {
+ "header": "NavigationView with PaneDisplayMode set to Top",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample\u0022 Header=\u0022This is Header Text\u0022 PaneDisplayMode=\u0022Top\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item1\u0022 Tag=\u0022SamplePage1\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item2\u0022 Tag=\u0022SamplePage2\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item3\u0022 Tag=\u0022SamplePage3\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item4\u0022 Tag=\u0022SamplePage4\u0022 /\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame\u0022/\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "NavigationviewPanedisplaymodeTop.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationviewPanedisplaymodeTop.txt",
+ "name": "Panedisplaymode Top"
+ }
+ },
+ {
+ "header": "NavigationView that switches pane orientation based on window width",
+ "xaml": "\u003C!-- Put the following VisualStateGroup(s) inside the first component of your Page --\u003E\n\u003CVisualStateManager.VisualStateGroups\u003E\n \u003CVisualStateGroup\u003E\n \u003CVisualState\u003E\n \u003CVisualState.StateTriggers\u003E\n \u003CAdaptiveTrigger MinWindowWidth=\u0022{x:Bind nvSample.CompactModeThresholdWidth}\u0022 /\u003E\n \u003C/VisualState.StateTriggers\u003E\n \u003CVisualState.Setters\u003E\n \u003CSetter Target=\u0022nvSample.PaneDisplayMode\u0022 Value=\u0022Top\u0022 /\u003E\n \u003C/VisualState.Setters\u003E\n \u003C/VisualState\u003E\n \u003C/VisualStateGroup\u003E\n\u003C/VisualStateManager.VisualStateGroups \u003E\n\n\u003CNavigationView x:Name=\u0022nvSample\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item1\u0022 Tag=\u0022SamplePage1\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item2\u0022 Tag=\u0022SamplePage2\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item3\u0022 Tag=\u0022SamplePage3\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item4\u0022 Tag=\u0022SamplePage4\u0022 /\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame\u0022/\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "NavigationviewSwitchesPaneOrientation.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationviewSwitchesPaneOrientation.txt",
+ "name": "Switches Pane Orientation"
+ }
+ },
+ {
+ "header": "Tying selection and focus - Tabs",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample\u0022 PaneDisplayMode=\u0022Top\u0022 \n SelectionFollowsFocus=\u0022Enabled\u0022 IsBackButtonVisible=\u0022Collapsed\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Icon=\u0022Play\u0022 Content=\u0022Item1\u0022 x:Name=\u0022SamplePage1Item\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Save\u0022 Content=\u0022Item2\u0022 x:Name=\u0022SamplePage2Item\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Refresh\u0022 Content=\u0022Item3\u0022 x:Name=\u0022SamplePage3Item\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Download\u0022 Content=\u0022Item4\u0022 x:Name=\u0022SamplePage4Item\u0022 /\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame\u0022/\u003E\n\u003C/NavigationView\u003E",
+ "code": "//C# code behind\nprivate void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)\n{\n FrameNavigationOptions navOptions = new FrameNavigationOptions();\n navOptions.TransitionInfoOverride = args.RecommendedNavigationTransitionInfo;\n if (sender.PaneDisplayMode == NavigationViewPaneDisplayMode.Top)\n {\n navOptions.IsNavigationStackEnabled = False;\n }\n Type pageType;\n if (args.InvokedItem == SamplePage1Item) \n {\n pageType = typeof(SamplePage1);\n }\n else if (args.InvokedItem == SamplePage2Item) \n {\n pageType = typeof(SamplePage2);\n }\n else if (args.InvokedItem == SamplePage3Item) \n {\n pageType = typeof(SamplePage3);\n }\n else if (args.InvokedItem == SamplePage4Item) \n {\n pageType = typeof(SamplePage4);\n }\n ContentFrame.NavigateToType(pageType, null, navOptions);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "NavigationViewTyingSelectionFocusTabs.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationViewTyingSelectionFocusTabs.txt",
+ "name": "Tying Selection Focus Tabs"
+ }
+ },
+ {
+ "header": "Data binding",
+ "code": "//C# code behind\nCategories = new ObservableCollection\u003CCategoryBase\u003E(); \nCategories.Add(new Category { Name = \u0022Category 1\u0022, Glyph = Symbol.Home, Tooltip = \u0022This is category 1\u0022 }); \nCategories.Add(new Category { Name = \u0022Category 2\u0022, Glyph = Symbol.Keyboard, Tooltip = \u0022This is category 2\u0022 }); \nCategories.Add(new Category { Name = \u0022Category 3\u0022, Glyph = Symbol.Library, Tooltip = \u0022This is category 3\u0022 }); \nCategories.Add(new Category { Name = \u0022Category 4\u0022, Glyph = Symbol.Mail, Tooltip = \u0022This is category 4\u0022 }); \n\npublic class CategoryBase { } \n\npublic class Category : CategoryBase\n{\n public string Name { get; set; } = string.Empty;\n public string Tooltip { get; set; } = string.Empty;\n public Symbol Glyph { get; set; }\n}\n\npublic class Separator : CategoryBase { }\n\npublic class Header : CategoryBase\n{\n public string Name { get; set; }\n}\n\n[ContentProperty(Name = \u0022ItemTemplate\u0022)]\nclass MenuItemTemplateSelector : DataTemplateSelector\n{\n public DataTemplate? ItemTemplate { get; set; }\n\n protected override DataTemplate? SelectTemplateCore(object item)\n {\n return item is Separator ? SeparatorTemplate : item is Header ? HeaderTemplate : ItemTemplate;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "NavigationViewDataBinding.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationViewDataBinding.txt",
+ "name": "Data Binding",
+ "xamlOmittedUnboundPrefixes": [
+ "local"
+ ]
+ }
+ },
+ {
+ "header": "NavigationView with Footer Menu Items",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample9\u0022 \n Header=\u0022This is Header Text\u0022 \n PaneDisplayMode=\u0022Left\u0022 \n SelectionChanged=\u0022NavigationView_SelectionChanged9\u0022\n IsSettingsVisible=\u0022False\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Browse\u0022 Tag=\u0022SamplePage1\u0022 Icon=\u0022Library\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Track an Order\u0022 Tag=\u0022SamplePage2\u0022 Icon=\u0022Map\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Order History\u0022 Tag=\u0022SamplePage3\u0022 Icon=\u0022Tag\u0022 /\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CNavigationView.FooterMenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Account\u0022 Tag=\u0022SamplePage4\u0022 Icon=\u0022Contact\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Your Cart\u0022 Tag=\u0022SamplePage5\u0022 Icon=\u0022Shop\u0022 /\u003E\n \u003CNavigationViewItem Content=\u0022Help\u0022 Tag=\u0022SamplePage5\u0022 Icon=\u0022Help\u0022 /\u003E\n \u003C/NavigationView.FooterMenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame9\u0022 /\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "NavigationviewFooterMenuItems.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationviewFooterMenuItems.txt",
+ "name": "Footer Menu Items"
+ }
+ },
+ {
+ "header": "Hierarchical NavigationView",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample8\u0022 Grid.Row=\u00221\u0022 Height=\u0022460\u0022\n PaneDisplayMode=\u0022Left\u0022 \n IsTabStop=\u0022False\u0022 \n SelectionChanged=\u0022NavigationView_SelectionChanged8\u0022\u003E\n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Home\u0022 Icon=\u0022Home\u0022 ToolTipService.ToolTip=\u0022Home\u0022 Tag=\u0022SamplePage1\u0022/\u003E\n \u003CNavigationViewItem Content=\u0022Account\u0022 Icon=\u0022Contact\u0022 ToolTipService.ToolTip=\u0022Account\u0022 Tag=\u0022SamplePage2\u0022\u003E\n \u003CNavigationViewItem.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Mail\u0022 Icon=\u0022Mail\u0022 ToolTipService.ToolTip=\u0022Mail\u0022 Tag=\u0022SamplePage3\u0022/\u003E\n \u003CNavigationViewItem Content=\u0022Calendar\u0022 Icon=\u0022Calendar\u0022 ToolTipService.ToolTip=\u0022Calendar\u0022 Tag=\u0022SamplePage4\u0022/\u003E\n \u003C/NavigationViewItem.MenuItems\u003E\n \u003C/NavigationViewItem\u003E\n \u003CNavigationViewItem Content=\u0022Document options\u0022 Icon=\u0022Page2\u0022 ToolTipService.ToolTip=\u0022Document options\u0022 SelectsOnInvoked=\u0022False\u0022\u003E\n \u003CNavigationViewItem.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Create new\u0022 Icon=\u0022NewFolder\u0022 ToolTipService.ToolTip=\u0022Create new\u0022 Tag=\u0022SamplePage5\u0022/\u003E\n \u003CNavigationViewItem Content=\u0022Upload file\u0022 Icon=\u0022OpenLocal\u0022 ToolTipService.ToolTip=\u0022Upload file\u0022 Tag=\u0022SamplePage6\u0022/\u003E\n \u003C/NavigationViewItem.MenuItems\u003E\n \u003C/NavigationViewItem\u003E\n \u003C/NavigationView.MenuItems\u003E\n \u003CFrame x:Name=\u0022contentFrame8\u0022 /\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "HierarchicalNavigationview.txt",
+ "source": "WinUIGallery/Samples/NavigationView/HierarchicalNavigationview.txt",
+ "name": "Hierarchical Navigationview"
+ }
+ },
+ {
+ "header": "API in action",
+ "xaml": "\u003CNavigationView x:Name=\u0022nvSample\u0022\n IsSettingsVisible=\u0022True\u0022\n IsBackEnabled=\u0022False\u0022\n SelectionChanged=\u0022NavigationView_SelectionChanged\u0022\n Header=\u0022Header\u0022\n AlwaysShowHeader=\u0022True\u0022\n PaneTitle=\u0022Pane Title\u0022\n PaneDisplayMode=\u0022Left\u0022 \n ExpandedModeThresholdWidth=\u0022500\u0022\n IsTabStop=\u0022False\u0022\u003E\n \n \u003CNavigationView.MenuItems\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item1\u0022 Tag=\u0022SamplePage1\u0022 x:Name=\u0022SamplePage1Item\u0022\u003E\n \u003CNavigationViewItem.Icon\u003E\n \u003CSymbolIcon Symbol=\u0022Play\u0022 /\u003E\n \u003C/NavigationViewItem.Icon\u003E\n \u003C/NavigationViewItem\u003E\n \u003CNavigationViewItemHeader Content=\u0022Actions\u0022/\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item2\u0022 Tag=\u0022SamplePage2\u0022 x:Name=\u0022SamplePage2Item\u0022 SelectsOnInvoked=\u0022True\u0022\u003E\n \u003CNavigationViewItem.Icon\u003E\n \u003CSymbolIcon Symbol=\u0022Save\u0022 /\u003E\n \u003C/NavigationViewItem.Icon\u003E\n \u003C/NavigationViewItem\u003E\n \u003CNavigationViewItem Content=\u0022Menu Item3\u0022 Tag=\u0022SamplePage3\u0022 x:Name=\u0022SamplePage3Item\u0022\u003E\n \u003CNavigationViewItem.Icon\u003E\n \u003CSymbolIcon Symbol=\u0022Refresh\u0022 /\u003E\n \u003C/NavigationViewItem.Icon\u003E\n \u003C/NavigationViewItem\u003E\n \u003C/NavigationView.MenuItems\u003E\n \n \u003CNavigationView.PaneCustomContent\u003E\n \u003CHyperlinkButton x:Name=\u0022PaneHyperlink\u0022 Content=\u0022More info\u0022 Margin=\u002212,0\u0022 Visibility=\u0022Collapsed\u0022 /\u003E\n \u003C/NavigationView.PaneCustomContent\u003E\n \u003CNavigationView.PaneFooter\u003E\n \u003CStackPanel x:Name=\u0022FooterStackPanel\u0022 Orientation=\u0022Vertical\u0022 Visibility=\u0022Collapsed\u0022\u003E\n \u003CNavigationViewItem Icon=\u0022Download\u0022 AutomationProperties.Name=\u0022download\u0022 /\u003E\n \u003CNavigationViewItem Icon=\u0022Favorite\u0022 AutomationProperties.Name=\u0022favorite\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/NavigationView.PaneFooter\u003E\n\n \u003CFrame x:Name=\u0022contentFrame\u0022 /\u003E\n\u003C/NavigationView\u003E",
+ "gallery": {
+ "snippet": "NavigationViewApiAction.txt",
+ "source": "WinUIGallery/Samples/NavigationView/NavigationViewApiAction.txt",
+ "name": "Api Action",
+ "xamlPlaceholdersDropped": [
+ "BackButtonVis",
+ "SelectionFollowsFocus",
+ "NavViewASB"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "numberbox",
+ "name": "NumberBox",
+ "description": "A text control used for numeric input and evaluation of algebraic equations.",
+ "details": "Use NumberBox to allow users to enter algebraic equations and numeric input in your app.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "TextBox",
+ "TextBlock",
+ "RichTextBlock",
+ "RichEditBox"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Windows.Globalization.NumberFormatting"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "numeric input",
+ "spinner",
+ "calculator"
+ ],
+ "docs": [
+ {
+ "title": "NumberBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.numberbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/number-box"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "NumberBox",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/NumberBox/NumberBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/NumberBox/NumberBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#RichTextBlock",
+ "microsoft/WinUI-Gallery#TextBlock",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A NumberBox that evaluates expressions.",
+ "xaml": "\u003CNumberBox Header=\u0022Enter an expression:\u0022 Value=\u0022NaN\u0022 PlaceholderText=\u00221 \u002B 2^2\u0022 AcceptsExpression=\u0022True\u0022 /\u003E",
+ "gallery": {
+ "snippet": "NumberboxEvaluatesExpressions.txt",
+ "source": "WinUIGallery/Samples/NumberBox/NumberboxEvaluatesExpressions.txt",
+ "name": "Evaluates Expressions"
+ }
+ },
+ {
+ "header": "A NumberBox with a spin button.",
+ "xaml": "\u003CNumberBox\n x:Name=\u0022NumberBoxSpinButtonPlacementExample\u0022\n Header=\u0022Enter an integer:\u0022 \n Value=\u00221\u0022 \n SpinButtonPlacementMode=\u0022Inline\u0022\n SmallChange=\u002210\u0022\n LargeChange=\u0022100\u0022 /\u003E",
+ "gallery": {
+ "snippet": "NumberboxSpinButton.txt",
+ "source": "WinUIGallery/Samples/NumberBox/NumberboxSpinButton.txt",
+ "name": "Spin Button"
+ }
+ },
+ {
+ "header": "A formatted NumberBox that rounds to the nearest 0.25.",
+ "xaml": "\u003CNumberBox x:Name=\u0022FormattedNumberBox\u0022 Header=\u0022Enter an dollar amount:\u0022 PlaceholderText=\u00220.00\u0022 /\u003E",
+ "code": "private void SetNumberBoxNumberFormatter()\n{\n IncrementNumberRounder rounder = new IncrementNumberRounder();\n rounder.Increment = 0.25;\n rounder.RoundingAlgorithm = RoundingAlgorithm.RoundHalfUp;\n\n DecimalFormatter formatter = new DecimalFormatter();\n formatter.IntegerDigits = 1;\n formatter.FractionDigits = 2;\n formatter.NumberRounder = rounder;\n FormattedNumberBox.NumberFormatter = formatter;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "FormattedNumberboxRoundsNearest.txt",
+ "source": "WinUIGallery/Samples/NumberBox/FormattedNumberboxRoundsNearest.txt",
+ "name": "Formatted Numberbox Rounds Nearest"
+ }
+ }
+ ]
+ },
+ {
+ "id": "pagercontrol",
+ "name": "PagerControl",
+ "description": "A control that lets users navigate through a numbered collection of pages.",
+ "details": "PagerControl provides numbered page navigation with multiple display modes and configurable navigation buttons.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "PipsPager",
+ "ItemsRepeater",
+ "ListView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "pagination",
+ "pages",
+ "navigation"
+ ],
+ "gallery": {
+ "uniqueId": "PagerControl",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/PagerControl/PagerControlPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PagerControl/PagerControlPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#PipsPager"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic pager",
+ "xaml": "\u003CPagerControl\n NumberOfPages=\u002212\u0022\n PrefixText=\u0022Page\u0022\n SelectedPageIndex=\u00222\u0022\n SuffixText=\u0022of\u0022 /\u003E",
+ "gallery": {
+ "snippet": "PagerControlBasic.txt",
+ "source": "WinUIGallery/Samples/PagerControl/PagerControlBasic.txt",
+ "name": "Basic"
+ }
+ },
+ {
+ "header": "Pager display modes",
+ "xaml": "\u003CStackPanel Spacing=\u002220\u0022\u003E\n \u003CPagerControl\n DisplayMode=\u0022NumberBox\u0022\n NumberOfPages=\u002250\u0022\n PrefixText=\u0022Page\u0022\n SelectedPageIndex=\u00229\u0022\n SuffixText=\u0022of\u0022 /\u003E\n \u003CPagerControl\n DisplayMode=\u0022ButtonPanel\u0022\n FirstButtonVisibility=\u0022Visible\u0022\n LastButtonVisibility=\u0022Visible\u0022\n NextButtonVisibility=\u0022Visible\u0022\n NumberOfPages=\u002220\u0022\n PreviousButtonVisibility=\u0022Visible\u0022\n SelectedPageIndex=\u00224\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "PagerControlDisplayModes.txt",
+ "source": "WinUIGallery/Samples/PagerControl/PagerControlDisplayModes.txt",
+ "name": "Display Modes"
+ }
+ },
+ {
+ "header": "Unbounded pagers",
+ "xaml": "\u003CStackPanel Spacing=\u002220\u0022\u003E\n \u003CPagerControl\n DisplayMode=\u0022NumberBox\u0022\n NumberOfPages=\u0022-1\u0022\n PrefixText=\u0022Page\u0022\n SelectedPageIndex=\u002299\u0022 /\u003E\n \u003CPagerControl\n DisplayMode=\u0022ButtonPanel\u0022\n FirstButtonVisibility=\u0022Visible\u0022\n NextButtonVisibility=\u0022Visible\u0022\n NumberOfPages=\u0022-1\u0022\n PreviousButtonVisibility=\u0022Visible\u0022\n SelectedPageIndex=\u002299\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "PagerControlUnbounded.txt",
+ "source": "WinUIGallery/Samples/PagerControl/PagerControlUnbounded.txt",
+ "name": "Unbounded"
+ }
+ }
+ ]
+ },
+ {
+ "id": "pagetransition",
+ "name": "Page Transitions",
+ "description": "Page transitions provide visual feedback about the relationship between pages.",
+ "details": "Page transitions provide visual feedback about the relationship between pages.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media.Animation",
+ "relatedControls": [
+ "Connected Animation",
+ "Theme Transitions"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media.Animation"
+ ],
+ "curatedKeywords": [
+ "page transition",
+ "navigation transition",
+ "NavigationTransitionInfo"
+ ],
+ "docs": [
+ {
+ "title": "NavigationThemeTransition - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Media.Animation.NavigationThemeTransition"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/page-transitions"
+ },
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "PageTransition",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/PageTransition/PageTransitionPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PageTransition/PageTransitionPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ConnectedAnimation",
+ "microsoft/WinUI-Gallery#ThemeTransition"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Page transitions",
+ "xaml": "\u003CFrame x:Name=\u0022ContentFrame\u0022\u003E\n \u003CFrame.ContentTransitions\u003E\n \u003CTransitionCollection\u003E\n \u003CNavigationThemeTransition /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/Frame.ContentTransitions\u003E\n\u003C/Frame\u003E",
+ "code": "ContentFrame.Navigate(typeof(SamplePage), null);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "PageTransitions.txt",
+ "source": "WinUIGallery/Samples/PageTransition/PageTransitions.txt",
+ "name": "s"
+ }
+ }
+ ]
+ },
+ {
+ "id": "parallaxview",
+ "name": "ParallaxView",
+ "description": "A container control that provides the parallax effect when scrolling.",
+ "details": "A container control that provides the parallax effect when scrolling.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ScrollView",
+ "ScrollViewer"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "scrolling effect"
+ ],
+ "docs": [
+ {
+ "title": "ParallaxView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.Parallaxview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/parallax"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ParallaxView",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/ParallaxView/ParallaxViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ParallaxView/ParallaxViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ScrollView",
+ "microsoft/WinUI-Gallery#ScrollViewer"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Parallax on a ListView",
+ "xaml": "\u003CGrid\u003E\n \u003CParallaxView Source=\u0022{Binding ElementName=listView}\u0022 VerticalShift=\u0022500\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 /\u003E\n \u003C/ParallaxView\u003E\n \u003CListView x:Name=\u0022listView\u0022 ItemsSource=\u0022{x:Bind Items}\u0022\u003E\n \u003CListView.Header\u003E\n \u003CTextBlock Text=\u0022Scroll the list to see parallaxing of image\u0022 /\u003E\n \u003C/ListView.Header\u003E\n \u003C/ListView\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "ParallaxViewParallaxListview.txt",
+ "source": "WinUIGallery/Samples/ParallaxView/ParallaxViewParallaxListview.txt",
+ "name": "Parallax Listview"
+ }
+ },
+ {
+ "header": "Parallax with a ScrollView",
+ "xaml": "\u003CGrid\u003E\n \u003CParallaxView Source=\u0022{Binding ElementName=scrollView}\u0022 VerticalShift=\u0022500\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022/\u003E\n \u003C/ParallaxView\u003E\n \u003CTextBlock Text=\u0022Scroll the rectangles to see parallaxing of image\u0022 MaxWidth=\u0022280\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Top\u0022 Foreground=\u0022White\u0022\n FontSize=\u002228\u0022 TextWrapping=\u0022WrapWholeWords\u0022/\u003E\n \u003CScrollView x:Name=\u0022scrollView\u0022 Width=\u0022150\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CStackPanel\u003E\n \u003CRectangle Fill=\u0022AliceBlue\u0022 Height=\u0022150\u0022/\u003E\n \u003C!-- ... --\u003E\n \u003CRectangle Fill=\u0022Cyan\u0022 Height=\u0022150\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/ScrollView\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "ParallaxViewParallaxScrollview.txt",
+ "source": "WinUIGallery/Samples/ParallaxView/ParallaxViewParallaxScrollview.txt",
+ "name": "Parallax Scrollview"
+ }
+ }
+ ]
+ },
+ {
+ "id": "passwordbox",
+ "name": "PasswordBox",
+ "description": "A control for entering passwords.",
+ "details": "A user can enter a single line of non-wrapping text in a PasswordBox control. The text is masked by characters that you can specify by using the PasswordChar property, and you can specify the maximum number of characters that the user can enter by setting the MaxLength property.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "TextBox",
+ "TextBlock",
+ "RichTextBlock",
+ "RichEditBox"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "secure input",
+ "reveal"
+ ],
+ "docs": [
+ {
+ "title": "PasswordBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.passwordbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/text-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "PasswordBox",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/PasswordBox/PasswordBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PasswordBox/PasswordBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#RichTextBlock",
+ "microsoft/WinUI-Gallery#TextBlock",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple PasswordBox.",
+ "xaml": "\u003CPasswordBox Width=\u0022300\u0022 AutomationProperties.Name=\u0022Simple PasswordBox\u0022/\u003E",
+ "gallery": {
+ "snippet": "SimplePasswordbox.txt",
+ "source": "WinUIGallery/Samples/PasswordBox/SimplePasswordbox.txt",
+ "name": "Simple Passwordbox"
+ }
+ },
+ {
+ "header": "A PasswordBox with header, placeholder text and custom character.",
+ "xaml": "\u003CPasswordBox Width=\u0022300\u0022 Header=\u0022Password\u0022 PlaceholderText=\u0022Enter your password\u0022 PasswordChar=\u0022#\u0022 /\u003E",
+ "gallery": {
+ "snippet": "PasswordboxHeaderPlaceholderText.txt",
+ "source": "WinUIGallery/Samples/PasswordBox/PasswordboxHeaderPlaceholderText.txt",
+ "name": "Header Placeholder Text"
+ }
+ },
+ {
+ "header": "A PasswordBox with reveal mode.",
+ "xaml": "\u003CPasswordBox Name=\u0022passworBoxWithRevealmode\u0022 Width=\u0022250\u0022 Margin=\u00220,0,8,0\u0022\n PasswordRevealMode=\u0022Hidden\u0022 AutomationProperties.Name=\u0022Sample password box\u0022/\u003E\n\u003CCheckBox Name=\u0022revealModeCheckBox\u0022 Content=\u0022Show password\u0022 IsChecked=\u0022False\u0022\n Checked=\u0022RevealModeCheckbox_Changed\u0022 Unchecked=\u0022RevealModeCheckbox_Changed\u0022/\u003E",
+ "code": "private void RevealModeCheckbox_Changed(object sender, RoutedEventArgs e)\n{\n if (revealModeCheckBox.IsChecked == true)\n {\n passworBoxWithRevealmode.PasswordRevealMode = PasswordRevealMode.Visible;\n }\n else\n {\n passworBoxWithRevealmode.PasswordRevealMode = PasswordRevealMode.Hidden;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "PasswordboxRevealMode.txt",
+ "source": "WinUIGallery/Samples/PasswordBox/PasswordboxRevealMode.txt",
+ "name": "Reveal Mode"
+ }
+ }
+ ]
+ },
+ {
+ "id": "personpicture",
+ "name": "PersonPicture",
+ "description": "Displays the picture of a person/contact.",
+ "details": "Displays the picture of a person/contact.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Image"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "avatar",
+ "contact photo"
+ ],
+ "docs": [
+ {
+ "title": "PersonPicture - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.PersonPicture"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/person-picture"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "PersonPicture",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/PersonPicture/PersonPicturePage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PersonPicture/PersonPicturePage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Image"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Select different looks for the person picture.",
+ "xaml": "\u003CPersonPicture ProfilePicture=\u0022https://learn.microsoft.com/windows/uwp/contacts-and-calendar/images/shoulder-tap-static-payload.png\u0022 /\u003E",
+ "gallery": {
+ "snippet": "PersonPictureSelectDifferentLooksPerson.txt",
+ "source": "WinUIGallery/Samples/PersonPicture/PersonPictureSelectDifferentLooksPerson.txt",
+ "name": "Select Different Looks Person"
+ }
+ }
+ ]
+ },
+ {
+ "id": "pipspager",
+ "name": "PipsPager",
+ "description": "A control to let the user navigate through a paginated collection when the page numbers do not need to be visually known.",
+ "details": "A PipsPager allows the user to navigate through a paginated collection and is independent of the content shown. Use this control when the content in the layout is not explicitly ordered by relevancy or you desire a glyph-based representation of numbered pages. PipsPagers are commonly used in photo viewers, app lists, carousels, and when display space is limited.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ScrollViewer",
+ "FlipView",
+ "ItemsRepeater"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "pagination",
+ "dots"
+ ],
+ "docs": [
+ {
+ "title": "PipsPager - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.pipspager"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/pipspager"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "PipsPager",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/PipsPager/PipsPagerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PipsPager/PipsPagerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#FlipView",
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#ScrollViewer"
+ ]
+ },
+ "samples": [
+ {
+ "header": "PipsPager integrated with a FlipView",
+ "xaml": "\u003CStackPanel\u003E\n \u003CFlipView x:Name=\u0022Gallery\u0022 MaxWidth=\u0022400\u0022 Height=\u0022270\u0022 ItemsSource=\u0022{x:Bind Pictures}\u0022\u003E\n \u003CFlipView.ItemTemplate\u003E\n \u003CDataTemplate x:DataType=\u0022x:String\u0022\u003E\n \u003CImage Source=\u0022{x:Bind Mode=OneTime}\u0022 /\u003E\n \u003C/DataTemplate\u003E\n \u003C/FlipView.ItemTemplate\u003E\n \u003C/FlipView\u003E\n \u003CPipsPager x:Name=\u0022FlipViewPipsPager\u0022\n HorizontalAlignment=\u0022Center\u0022\n Margin=\u00220, 12, 0, 0\u0022\n NumberOfPages=\u0022{x:Bind Pictures.Count}\u0022\n SelectedPageIndex=\u0022{x:Bind Path=Gallery.SelectedIndex, Mode=TwoWay}\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "PipspagerIntegratedFlipview.txt",
+ "source": "WinUIGallery/Samples/PipsPager/PipspagerIntegratedFlipview.txt",
+ "name": "Integrated Flipview"
+ }
+ },
+ {
+ "header": "PipsPager with options to change its orientation, button visibility, and wrap mode.",
+ "xaml": "\u003CPipsPager /\u003E",
+ "gallery": {
+ "snippet": "PipspagerOptionsChangeOrientation.txt",
+ "source": "WinUIGallery/Samples/PipsPager/PipspagerOptionsChangeOrientation.txt",
+ "name": "Options Change Orientation",
+ "xamlPlaceholdersDropped": [
+ "Orientation",
+ "PrevButton",
+ "NextButton",
+ "WrapMode"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "pivot",
+ "name": "Pivot",
+ "description": "Presents information from different sources in a tabbed view.",
+ "details": "Pivot is not recommended for Windows 11 design patterns. Please use the SelectorBar and SelectorBarItem. A Pivot allows you to show a collection of items from different sources in a tabbed view.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "SelectorBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl"
+ ],
+ "curatedKeywords": [
+ "tabs",
+ "tabbed view"
+ ],
+ "docs": [
+ {
+ "title": "Pivot - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.pivot"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/pivot"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Pivot",
+ "group": {
+ "id": "Navigation",
+ "title": "Navigation"
+ },
+ "page": "WinUIGallery/Samples/Pivot/PivotPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Pivot/PivotPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ItemsControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#SelectorBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic pivot.",
+ "xaml": "\u003CPivot Title=\u0022EMAIL\u0022\u003E\n \u003CPivotItem Header=\u0022All\u0022\u003E\n \u003CTextBlock Text=\u0022all emails go here.\u0022 /\u003E\n \u003C/PivotItem\u003E\n \u003CPivotItem Header=\u0022Unread\u0022\u003E\n \u003CTextBlock Text=\u0022unread emails go here.\u0022 /\u003E\n \u003C/PivotItem\u003E\n \u003CPivotItem Header=\u0022Flagged\u0022\u003E\n \u003CTextBlock Text=\u0022flagged emails go here.\u0022 /\u003E\n \u003C/PivotItem\u003E\n \u003CPivotItem Header=\u0022Urgent\u0022\u003E\n \u003CTextBlock Text=\u0022urgent emails go here.\u0022 /\u003E\n \u003C/PivotItem\u003E\n\u003C/Pivot\u003E",
+ "gallery": {
+ "snippet": "BasicPivot.txt",
+ "source": "WinUIGallery/Samples/Pivot/BasicPivot.txt",
+ "name": "Basic Pivot"
+ }
+ }
+ ]
+ },
+ {
+ "id": "popup",
+ "name": "Popup",
+ "description": "A UI element displaying temporary content over existing interface.",
+ "details": "The Popup Control allows your app to display temporary content above other UI elements. It can be used for lightweight interactions such as tooltips, notifications, or custom floating panels to enhance user workflows or highlight specific parts of the interface.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls.Primitives",
+ "relatedControls": [
+ "ContentDialog"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "overlay",
+ "temporary content"
+ ],
+ "docs": [
+ {
+ "title": "Popup - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.popup"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Popup",
+ "group": {
+ "id": "DialogsAndFlyouts",
+ "title": "Dialogs \u0026 flyouts"
+ },
+ "page": "WinUIGallery/Samples/Popup/PopupPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Popup/PopupPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ContentDialog"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Popup with Offset Positioning",
+ "xaml": "\u003CGrid x:Name=\u0022Output\u0022 HorizontalAlignment=\u0022Left\u0022 VerticalAlignment=\u0022Top\u0022 \u003E\n \u003CButton Content=\u0022Show Popup (using Offset)\u0022 Click=\u0022ShowPopupOffsetClicked\u0022 /\u003E\n \u003CPopup x:Name=\u0022StandardPopup\u0022 VerticalOffset=\u00220\u0022 HorizontalOffset=\u0022200\u0022 IsLightDismissEnabled=\u0022True\u0022\u003E\n \u003CBorder Padding=\u002220\u0022 CornerRadius=\u0022{StaticResource OverlayCornerRadius}\u0022 Width=\u0022200\u0022 Height=\u0022160\u0022 BorderThickness=\u00221\u0022 BorderBrush=\u0022{ThemeResource SurfaceStrokeColorDefaultBrush}\u0022\n Background=\u0022{ThemeResource AcrylicBackgroundFillColorDefaultBrush}\u0022\u003E\n \u003CStackPanel HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022 Spacing=\u00228\u0022\u003E\n \u003CTextBlock Text=\u0022Simple Popup\u0022 FontSize=\u002216\u0022 HorizontalAlignment=\u0022Center\u0022 /\u003E\n \u003CButton Content=\u0022Close\u0022 Click=\u0022ClosePopupClicked\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/Border\u003E\n \u003C/Popup\u003E\n\u003C/Grid\u003E",
+ "code": "// Handles the Click event on the Button on the page and opens the Popup. \nprivate void ShowPopupOffsetClicked(object sender, RoutedEventArgs e)\n{\n // open the Popup if it isn\u0027t open already \n if (!StandardPopup.IsOpen) { StandardPopup.IsOpen = true; }\n}\n\n// Handles the Click event on the Button inside the Popup control and closes the Popup. \nprivate void ClosePopupClicked(object sender, RoutedEventArgs e)\n{\n // if the Popup is open, then close it \n if (StandardPopup.IsOpen) { StandardPopup.IsOpen = false; }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "PopupOffsetPositioning.txt",
+ "source": "WinUIGallery/Samples/Popup/PopupOffsetPositioning.txt",
+ "name": "Offset Positioning"
+ }
+ }
+ ]
+ },
+ {
+ "id": "progressbar",
+ "name": "ProgressBar",
+ "description": "Shows the apps progress on a task, or that the app is performing ongoing work that doesn\u0027t block user interaction.",
+ "details": "The ProgressBar has two different visual representations:\nIndeterminate - shows that a task is ongoing, but doesn\u0027t block user interaction.\nDeterminate - shows how much progress has been made on a known amount of work.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ProgressRing"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "RangeBase"
+ ],
+ "curatedKeywords": [
+ "loading",
+ "determinate",
+ "indeterminate"
+ ],
+ "docs": [
+ {
+ "title": "ProgressBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.ProgressBar"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/progress-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ProgressBar",
+ "group": {
+ "id": "StatusAndInfo",
+ "title": "Status \u0026 info"
+ },
+ "page": "WinUIGallery/Samples/ProgressBar/ProgressBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ProgressBar/ProgressBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "RangeBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ProgressRing"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An indeterminate progress bar.",
+ "xaml": "\u003CProgressBar Width=\u0022130\u0022 IsIndeterminate=\u0022True\u0022 /\u003E",
+ "gallery": {
+ "snippet": "IndeterminateProgressBar.txt",
+ "source": "WinUIGallery/Samples/ProgressBar/IndeterminateProgressBar.txt",
+ "name": "Indeterminate Progress Bar",
+ "xamlPlaceholdersDropped": [
+ "ShowPaused",
+ "ShowError"
+ ]
+ }
+ },
+ {
+ "header": "A determinate progress bar.",
+ "xaml": "\u003CProgressBar Width=\u0022130\u0022 /\u003E",
+ "gallery": {
+ "snippet": "DeterminateProgressBar.txt",
+ "source": "WinUIGallery/Samples/ProgressBar/DeterminateProgressBar.txt",
+ "name": "Determinate Progress Bar",
+ "xamlPlaceholdersDropped": [
+ "DeterminateProgressValue"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "progressring",
+ "name": "ProgressRing",
+ "description": "Shows the apps progress on a task, or that the app is performing ongoing work that does block user interaction.",
+ "details": "The ProgressRing has two different visual representations:\nIndeterminate - shows that a task is ongoing, but blocks user interaction.\nDeterminate - shows how much progress has been made on a known amount of work.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ProgressBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "loading",
+ "spinner",
+ "busy"
+ ],
+ "docs": [
+ {
+ "title": "ProgressRing - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.progressring"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/progress-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ProgressRing",
+ "group": {
+ "id": "StatusAndInfo",
+ "title": "Status \u0026 info"
+ },
+ "page": "WinUIGallery/Samples/ProgressRing/ProgressRingPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ProgressRing/ProgressRingPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ProgressBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "An indeterminate progress ring.",
+ "xaml": "\u003CProgressRing IsActive=\u0022True\u0022 Background=\u0022LightGray\u0022/\u003E",
+ "gallery": {
+ "snippet": "IndeterminateProgressRing.txt",
+ "source": "WinUIGallery/Samples/ProgressRing/IndeterminateProgressRing.txt",
+ "name": "Indeterminate Progress Ring"
+ }
+ },
+ {
+ "header": "A determinate progress ring.",
+ "xaml": "\u003CProgressRing Width=\u002260\u0022 Height=\u002260\u0022\n IsIndeterminate=\u0022False\u0022\n Background=\u0022LightGray\u0022/\u003E",
+ "gallery": {
+ "snippet": "DeterminateProgressRing.txt",
+ "source": "WinUIGallery/Samples/ProgressRing/DeterminateProgressRing.txt",
+ "name": "Determinate Progress Ring",
+ "xamlPlaceholdersDropped": [
+ "DeterminateProgressValue"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "pulltorefresh",
+ "name": "PullToRefresh",
+ "description": "Provides the ability to pull on a collection of items in a list/grid to refresh the contents of the collection.",
+ "details": "PullToRefresh lets a user pull down on a list of data using touch in order to retrieve more data. PullToRefresh is widely used on devices with a touch screen.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ScrollView",
+ "ScrollViewer",
+ "ListView"
+ ],
+ "usings": [
+ "Microsoft.UI.Composition",
+ "Microsoft.UI.Dispatching",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Hosting",
+ "Microsoft.UI.Xaml.Media",
+ "Microsoft.UI.Xaml.Media.Imaging",
+ "Microsoft.UI.Xaml.Navigation",
+ "System",
+ "System.Collections.ObjectModel",
+ "Windows.Foundation",
+ "Windows.Foundation.Metadata",
+ "Windows.UI.ViewManagement"
+ ],
+ "curatedKeywords": [
+ "pull to refresh",
+ "RefreshContainer",
+ "RefreshVisualizer"
+ ],
+ "docs": [
+ {
+ "title": "RefreshContainer - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.RefreshContainer"
+ },
+ {
+ "title": "RefreshVisualizer - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.RefreshVisualizer"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/pull-to-refresh"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "PullToRefresh",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/PullToRefresh/PullToRefreshPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/PullToRefresh/PullToRefreshPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#ScrollView",
+ "microsoft/WinUI-Gallery#ScrollViewer"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Basic PullToRefresh",
+ "xaml": "\u003CRefreshContainer x:Name=\u0022rc\u0022 RefreshRequested=\u0022rc_RefreshRequested\u0022\u003E\n \u003CListView x:Name=\u0022lv\u0022 Width=\u0022300\u0022 Height=\u0022300\u0022 BorderThickness=\u00221\u0022 BorderBrush=\u0022Black\u0022/\u003E\n\u003C/RefreshContainer\u003E",
+ "code": "ObservableCollection\u003Cstring\u003E items = new ObservableCollection\u003Cstring\u003E();\nlistview.ItemsSource = items;\n\nprivate void rc_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)\n{\n //Do some work to show new Content! Once the work is done, call RefreshCompletionDeferral.Complete()\n this.RefreshCompletionDeferral = args.GetDeferral();\n this.DoWork();\n}\n\nprivate void WorkCompleted()\n{\n items.Insert(0, \u0022NewControl\u0022);\n if (this.RefreshCompletionDeferral != null)\n {\n this.RefreshCompletionDeferral.Complete();\n this.RefreshCompletionDeferral.Dispose();\n this.RefreshCompletionDeferral = null;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "BasicPulltorefresh.txt",
+ "source": "WinUIGallery/Samples/PullToRefresh/BasicPulltorefresh.txt",
+ "name": "Basic Pulltorefresh"
+ }
+ },
+ {
+ "header": "Custom Icon PullToRefresh",
+ "xaml": "\u003CRefreshContainer x:Name=\u0022rc\u0022 RefreshRequested=\u0022rc_RefreshRequested\u0022\u003E\n \u003CRefreshContainer.Visualizer\u003E\n \u003CRefreshVisualizer RefreshStateChanged=\u0022rv2_RefreshStateChanged\u0022\u003E\n \u003CRefreshVisualizer.Content\u003E\n \u003CSymbolIcon Symbol=\u0022AddFriend\u0022/\u003E\n \u003C/RefreshVisualizer.Content\u003E\n \u003C/RefreshVisualizer\u003E\n \u003C/RefreshContainer.Visualizer\u003E\n \u003CListView x:Name=\u0022lv\u0022 Width=\u0022300\u0022 Height=\u0022300\u0022 BorderThickness=\u00221\u0022 BorderBrush=\u0022Black\u0022/\u003E\n\u003C/RefreshContainer\u003E",
+ "code": "ObservableCollection\u003Cstring\u003E items = new ObservableCollection\u003Cstring\u003E();\nlistview.ItemsSource = items;\n\nprivate void rc_RefreshRequested(RefreshContainer sender, RefreshRequestedEventArgs args)\n{\n //Do some work to show new Content! Once the work is done, call RefreshCompletionDeferral.Complete()\n this.RefreshCompletionDeferral = args.GetDeferral();\n this.DoWork();\n}\n\nprivate void WorkCompleted()\n{\n items.Insert(0, \u0022NewControl\u0022);\n if (this.RefreshCompletionDeferral != null)\n {\n this.RefreshCompletionDeferral.Complete();\n this.RefreshCompletionDeferral.Dispose();\n this.RefreshCompletionDeferral = null;\n }\n}\nprivate void rv2_RefreshStateChanged()\n{\n var visualizerContentVisual = ElementCompositionPreview.GetElementVisual(rv2.Content);\n visualizerContentVisual.StopAnimation(\u0022RotationAngle\u0022);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomIconPulltorefresh.txt",
+ "source": "WinUIGallery/Samples/PullToRefresh/CustomIconPulltorefresh.txt",
+ "name": "Custom Icon Pulltorefresh"
+ }
+ }
+ ]
+ },
+ {
+ "id": "radialgradientbrush",
+ "name": "RadialGradientBrush",
+ "description": "A brush to show radial gradients.",
+ "details": "Paints an area with a radial gradient. A center point defines the beginning of the gradient, and a radius defines the end point of the gradient.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media",
+ "relatedControls": [
+ "AcrylicBrush"
+ ],
+ "xmlnsImports": [
+ "xmlns:media=\u0022using:Microsoft.UI.Xaml.Media\u0022"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "Brush",
+ "XamlCompositionBrushBase"
+ ],
+ "curatedKeywords": [
+ "gradient",
+ "radial gradient",
+ "brush"
+ ],
+ "docs": [
+ {
+ "title": "RadialGradientBrush - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.RadialGradientBrush"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RadialGradientBrush",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/RadialGradientBrush/RadialGradientBrushPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RadialGradientBrush/RadialGradientBrushPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "Brush",
+ "XamlCompositionBrushBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Acrylic"
+ ]
+ },
+ "samples": [
+ {
+ "header": "RadialGradientBrush Sample",
+ "xaml": "\u003CRectangle Width=\u0022200\u0022 Height=\u0022200\u0022\u003E\n \u003CRectangle.Fill\u003E\n \u003Cmedia:RadialGradientBrush\u003E\n \u003CGradientStop Color=\u0022Yellow\u0022 Offset=\u00220.0\u0022 /\u003E\n \u003CGradientStop Color=\u0022Blue\u0022 Offset=\u00221\u0022 /\u003E\n \u003C/media:RadialGradientBrush\u003E\n \u003C/Rectangle.Fill\u003E\n\u003C/Rectangle\u003E",
+ "gallery": {
+ "snippet": "RadialgradientbrushSample.txt",
+ "source": "WinUIGallery/Samples/RadialGradientBrush/RadialgradientbrushSample.txt",
+ "name": "Sample",
+ "xamlPlaceholdersDropped": [
+ "MappingMode",
+ "CenterX",
+ "CenterY",
+ "RadiusX",
+ "RadiusY",
+ "OriginX",
+ "OriginY",
+ "SpreadMethod"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "radiobutton",
+ "name": "RadioButton",
+ "description": "A control that allows a user to select a single option from a group of options.",
+ "details": "Use RadioButton controls to let a user choose between mutually exclusive, related options. Generally contained within a RadioButtons group control.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "CheckBox",
+ "ToggleSwitch",
+ "ToggleButton"
+ ],
+ "usings": [
+ "Microsoft.UI",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "curatedKeywords": [
+ "RadioButtons",
+ "single selection",
+ "option"
+ ],
+ "docs": [
+ {
+ "title": "RadioButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.radiobutton"
+ },
+ {
+ "title": "RadioButtons - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.radiobuttons"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/radio-button"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RadioButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/RadioButton/RadioButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RadioButton/RadioButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase",
+ "ToggleButton"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CheckBox",
+ "microsoft/WinUI-Gallery#ToggleButton",
+ "microsoft/WinUI-Gallery#ToggleSwitch"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A group of RadioButton controls in a RadioButtons group.",
+ "xaml": "\u003CRadioButtons Header=\u0022Options:\u0022\u003E\n \u003CRadioButton Content=\u0022Option 1\u0022 Checked=\u0022RadioButton_Checked\u0022/\u003E\n \u003CRadioButton Content=\u0022Option 2\u0022 Checked=\u0022RadioButton_Checked\u0022/\u003E\n \u003CRadioButton Content=\u0022Option 3\u0022 Checked=\u0022RadioButton_Checked\u0022/\u003E\n\u003C/RadioButtons\u003E",
+ "gallery": {
+ "snippet": "RadioButtonGroup.txt",
+ "source": "WinUIGallery/Samples/RadioButton/RadioButtonGroup.txt",
+ "name": "Group"
+ }
+ },
+ {
+ "header": "Two RadioButtons controls with strings as options.",
+ "xaml": "\u003CRadioButtons x:Name=\u0022BackgroundRadioButtons\u0022 SelectedIndex=\u00220\u0022 MaxColumns=\u00223\u0022 Header=\u0022Background\u0022 SelectionChanged=\u0022BackgroundColor_SelectionChanged\u0022\u003E\n \u003Cx:String\u003EGreen\u003C/x:String\u003E\n \u003Cx:String\u003EYellow\u003C/x:String\u003E\n \u003Cx:String\u003EWhite\u003C/x:String\u003E\n\u003C/RadioButtons\u003E\n\u003CRadioButtons x:Name=\u0022BorderRadioButtons\u0022 SelectedIndex=\u00221\u0022 MaxColumns=\u00223\u0022 Header=\u0022Border\u0022 SelectionChanged=\u0022BorderBrush_SelectionChanged\u0022\u003E\n \u003Cx:String\u003EGreen\u003C/x:String\u003E\n \u003Cx:String\u003EYellow\u003C/x:String\u003E\n \u003Cx:String\u003EWhite\u003C/x:String\u003E\n\u003C/RadioButtons\u003E\n\n\u003CBorder x:Name=\u0022ControlOutput\u0022 BorderThickness=\u002210\u0022 BorderBrush=\u0022#FFFFD700\u0022 Background=\u0022#FFFFFFFF\u0022\n Height=\u002250\u0022 Margin=\u00220,10,0,10\u0022 /\u003E",
+ "code": "private void BackgroundColor_SelectionChanged(object sender, SelectionChangedEventArgs e)\n{\n if (ControlOutput != null \u0026\u0026 sender is RadioButtons rb)\n {\n string colorName = rb.SelectedItem as string;\n switch (colorName)\n {\n case \u0022Yellow\u0022:\n ControlOutput.Background = new SolidColorBrush(Colors.Yellow);\n break;\n case \u0022Green\u0022:\n ControlOutput.Background = new SolidColorBrush(Colors.Green);\n break;\n case \u0022White\u0022:\n ControlOutput.Background = new SolidColorBrush(Colors.White);\n break;\n }\n }\n}\n\nprivate void BorderBrush_SelectionChanged(object sender, SelectionChangedEventArgs e)\n{\n if (ControlOutput != null \u0026\u0026 sender is RadioButtons rb)\n {\n string colorName = rb.SelectedItem as string;\n switch (colorName)\n {\n case \u0022Yellow\u0022:\n ControlOutput.BorderBrush = new SolidColorBrush(Colors.Gold);\n break;\n case \u0022Green\u0022:\n ControlOutput.BorderBrush = new SolidColorBrush(Colors.DarkGreen);\n break;\n case \u0022White\u0022:\n ControlOutput.BorderBrush = new SolidColorBrush(Colors.White);\n break;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "RadioButtonStrings.txt",
+ "source": "WinUIGallery/Samples/RadioButton/RadioButtonStrings.txt",
+ "name": "Strings"
+ }
+ }
+ ]
+ },
+ {
+ "id": "ratingcontrol",
+ "name": "RatingControl",
+ "description": "Rate something 1 to 5 stars.",
+ "details": "Rate something 1 to 5 stars.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Slider",
+ "ComboBox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "stars",
+ "review"
+ ],
+ "docs": [
+ {
+ "title": "RatingControl - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.RatingControl"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/rating"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RatingControl",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/RatingControl/RatingControlPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RatingControl/RatingControlPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ComboBox",
+ "microsoft/WinUI-Gallery#Slider"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple RatingControl",
+ "xaml": "\u003CRatingControl AutomationProperties.Name=\u0022Simple RatingControl\u0022 Caption=\u0022312 ratings\u0022/\u003E",
+ "gallery": {
+ "snippet": "RatingControlSimple.txt",
+ "source": "WinUIGallery/Samples/RatingControl/RatingControlSimple.txt",
+ "name": "Simple",
+ "xamlPlaceholdersDropped": [
+ "IsClearEnabled",
+ "IsReadOnly"
+ ]
+ }
+ },
+ {
+ "header": "PlaceholderValue of RatingControl",
+ "xaml": "\u003CRatingControl AutomationProperties.Name=\u0022RatingControl with placeholder\u0022 /\u003E",
+ "gallery": {
+ "snippet": "RatingControlPlaceholder.txt",
+ "source": "WinUIGallery/Samples/RatingControl/RatingControlPlaceholder.txt",
+ "name": "Placeholder",
+ "xamlPlaceholdersDropped": [
+ "Slider"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "relativepanel",
+ "name": "RelativePanel",
+ "description": "A panel that uses relationships between elements to define layout.",
+ "details": "Use a RelativePanel to layout elements by defining the relationships between elements and in relation to the panel.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Grid",
+ "StackPanel",
+ "Border",
+ "Canvas",
+ "Viewbox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "relative layout",
+ "positioning"
+ ],
+ "docs": [
+ {
+ "title": "RelativePanel - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.relativepanel"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/layout-panels"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RelativePanel",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/RelativePanel/RelativePanelPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RelativePanel/RelativePanelPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Border",
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#Viewbox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A RelativePanel control.",
+ "xaml": "\u003CRelativePanel Width=\u0022300\u0022\u003E\n \u003CRectangle x:Name=\u0022Rectangle1\u0022 Fill=\u0022Red\u0022 Height=\u002250\u0022 Width=\u002250\u0022/\u003E\n \u003CRectangle x:Name=\u0022Rectangle2\u0022 Fill=\u0022Blue\u0022 Height=\u002250\u0022 Width=\u002250\u0022 RelativePanel.RightOf=\u0022Rectangle1\u0022 Margin=\u00228,0,0,0\u0022/\u003E\n \u003CRectangle x:Name=\u0022Rectangle3\u0022 Fill=\u0022Green\u0022 Height=\u002250\u0022 Width=\u002250\u0022 RelativePanel.AlignRightWithPanel=\u0022True\u0022/\u003E\n \u003CRectangle x:Name=\u0022Rectangle4\u0022 Fill=\u0022Yellow\u0022 Height=\u002250\u0022 Width=\u002250\u0022 RelativePanel.Below=\u0022Rectangle3\u0022 RelativePanel.AlignHorizontalCenterWith=\u0022Rectangle3\u0022 Margin=\u00220,8,0,0\u0022/\u003E\n\u003C/RelativePanel\u003E",
+ "gallery": {
+ "snippet": "RelativepanelControl.txt",
+ "source": "WinUIGallery/Samples/RelativePanel/RelativepanelControl.txt",
+ "name": "Control"
+ }
+ }
+ ]
+ },
+ {
+ "id": "repeatbutton",
+ "name": "RepeatButton",
+ "description": "A button that raises its Click event repeatedly from the time it\u0027s pressed until it\u0027s released.",
+ "details": "The RepeatButton control is like a standard Button, except that the Click event occurs continuously while the user presses the RepeatButton.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls.Primitives",
+ "relatedControls": [
+ "Button",
+ "ToggleButton",
+ "HyperlinkButton",
+ "AppBarButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "curatedKeywords": [
+ "hold button"
+ ],
+ "docs": [
+ {
+ "title": "RepeatButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.repeatbutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RepeatButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/RepeatButton/RepeatButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RepeatButton/RepeatButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#HyperlinkButton",
+ "microsoft/WinUI-Gallery#ToggleButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple RepeatButton with text content.",
+ "xaml": "\u003CRepeatButton Content=\u0022Click and hold\u0022 Click=\u0022RepeatButton_Click\u0022 /\u003E",
+ "gallery": {
+ "snippet": "RepeatButtonSimple.txt",
+ "source": "WinUIGallery/Samples/RepeatButton/RepeatButtonSimple.txt",
+ "name": "Simple"
+ }
+ }
+ ]
+ },
+ {
+ "id": "richeditbox",
+ "name": "RichEditBox",
+ "description": "A rich text editing control that supports formatted text, hyperlinks, and other rich content.",
+ "details": "You can use a RichEditBox control to enter and edit rich text documents that contain formatted text, hyperlinks, and images. By default, the RichEditBox supports spell checking. You can make a RichEditBox read-only by setting its IsReadOnly property to true.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NumberBox",
+ "TextBox",
+ "RichTextBlock",
+ "TextBlock"
+ ],
+ "usings": [
+ "Microsoft.UI.Text",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Input",
+ "Microsoft.UI.Xaml.Media",
+ "Microsoft.Windows.Storage.Pickers",
+ "System",
+ "System.Collections.Generic",
+ "System.Diagnostics",
+ "System.Xml.Linq",
+ "Windows.Foundation.Metadata",
+ "Windows.Storage",
+ "Windows.Storage.Provider",
+ "Windows.Storage.Streams"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "rich text editor",
+ "RTF",
+ "formatted text",
+ "editor"
+ ],
+ "docs": [
+ {
+ "title": "RichEditBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.richeditbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/text-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RichEditBox",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/RichEditBox/RichEditBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RichEditBox/RichEditBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "badges": [
+ "Updated"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#NumberBox",
+ "microsoft/WinUI-Gallery#RichTextBlock",
+ "microsoft/WinUI-Gallery#TextBlock",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple text editor using RichEditBox.",
+ "xaml": "\u003CRichEditBox x:Name=\u0022editor\u0022 AutomationProperties.Name=\u0022simple text editor\u0022/\u003E",
+ "gallery": {
+ "snippet": "SimpleTextEditorRicheditbox.txt",
+ "source": "WinUIGallery/Samples/RichEditBox/SimpleTextEditorRicheditbox.txt",
+ "name": "Simple Text Editor Richeditbox"
+ }
+ },
+ {
+ "header": "Customizing RichEditBox\u0027s CommandBarFlyout - Adding \u0027Share\u0027",
+ "xaml": "\u003CRichEditBox x:Name=\u0022REBCustom\u0022 \n AutomationProperties.Name=\u0022editor with custom menu\u0022\n Width=\u0022800\u0022 Height=\u0022200\u0022 \n Loaded=\u0022REBCustom_Loaded\u0022 \n Unloaded=\u0022REBCustom_Unloaded\u0022/\u003E",
+ "code": "private void Menu_Opening(object sender, object e)\n{\n if (sender is not CommandBarFlyout myFlyout)\n {\n return;\n }\n\n if (myFlyout.Target == REBCustom)\n {\n AppBarButton myButton = new AppBarButton();\n myButton.Command = new StandardUICommand(StandardUICommandKind.Share);\n myFlyout.PrimaryCommands.Add(myButton);\n }\n}\n\nprivate void REBCustom_Loaded(object sender, RoutedEventArgs e)\n{\n REBCustom.SelectionFlyout.Opening \u002B= Menu_Opening;\n REBCustom.ContextFlyout.Opening \u002B= Menu_Opening;\n}\n\nprivate void REBCustom_Unloaded(object sender, RoutedEventArgs e)\n{\n REBCustom.SelectionFlyout.Opening -= Menu_Opening;\n REBCustom.ContextFlyout.Opening -= Menu_Opening;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomizingRicheditboxCommandbarflyoutAdding.txt",
+ "source": "WinUIGallery/Samples/RichEditBox/CustomizingRicheditboxCommandbarflyoutAdding.txt",
+ "name": "Customizing Richeditbox Commandbarflyout Adding"
+ }
+ },
+ {
+ "header": "A custom editor with RichEditBox.",
+ "xaml": "\u003CRelativePanel Margin=\u00220,0,0,20\u0022 HorizontalAlignment=\u0022Stretch\u0022\u003E\n \u003CRelativePanel.Resources\u003E\n \u003CStyle TargetType=\u0022Button\u0022\u003E\n \u003CSetter Property=\u0022BorderThickness\u0022 Value=\u00220\u0022 /\u003E\n \u003CSetter Property=\u0022Background\u0022 Value=\u0022Transparent\u0022/\u003E\n \u003CSetter Property=\u0022Margin\u0022 Value=\u00220,0,8,0\u0022 /\u003E\n \u003C/Style\u003E\n \u003C/RelativePanel.Resources\u003E\n \u003CButton x:Name=\u0022openFileButton\u0022 Click=\u0022OpenButton_Click\u0022 AutomationProperties.Name=\u0022Open file\u0022 ToolTipService.ToolTip=\u0022Open file\u0022\u003E\n \u003CButton.Content\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE8E5;\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022SaveButton_Click\u0022 AutomationProperties.Name=\u0022Save file\u0022 ToolTipService.ToolTip=\u0022Save file\u0022 \n RelativePanel.RightOf=\u0022openFileButton\u0022\u003E\n \u003CButton.Content\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE74E;\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton AutomationProperties.Name=\u0022Bold\u0022 ToolTipService.ToolTip=\u0022Bold\u0022 Click=\u0022BoldButton_Click\u0022 \n RelativePanel.LeftOf=\u0022italicButton\u0022 \u003E\n \u003CButton.Content\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE8DD;\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton x:Name=\u0022italicButton\u0022 Click=\u0022ItalicButton_Click\u0022 AutomationProperties.Name=\u0022Italic\u0022 ToolTipService.ToolTip=\u0022Italic\u0022 \n RelativePanel.LeftOf=\u0022fontColorButton\u0022\u003E\n \u003CButton.Content\u003E\n \u003CFontIcon Glyph=\u0022\u0026#xE8DB;\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n\n \u003CDropDownButton x:Name=\u0022fontColorButton\u0022 AutomationProperties.Name=\u0022Font color\u0022\n BorderThickness=\u00220\u0022 ToolTipService.ToolTip=\u0022Font color\u0022\n Background=\u0022Transparent\u0022 \n RelativePanel.AlignRightWithPanel=\u0022True\u0022\u003E\n \u003CSymbolIcon Symbol=\u0022FontColor\u0022/\u003E\n \u003CDropDownButton.Flyout\u003E\n \u003CFlyout Placement=\u0022Bottom\u0022\u003E\n \u003CVariableSizedWrapGrid Orientation=\u0022Horizontal\u0022 MaximumRowsOrColumns=\u00223\u0022\u003E\n \u003CVariableSizedWrapGrid.Resources\u003E\n \u003CStyle TargetType=\u0022Rectangle\u0022\u003E\n \u003CSetter Property=\u0022Width\u0022 Value=\u002232\u0022/\u003E\n \u003CSetter Property=\u0022Height\u0022 Value=\u002232\u0022/\u003E\n \u003C/Style\u003E\n \u003CStyle TargetType=\u0022Button\u0022\u003E\n \u003CSetter Property=\u0022Padding\u0022 Value=\u00220\u0022/\u003E\n \u003CSetter Property=\u0022MinWidth\u0022 Value=\u00220\u0022/\u003E\n \u003CSetter Property=\u0022MinHeight\u0022 Value=\u00220\u0022/\u003E\n \u003CSetter Property=\u0022Margin\u0022 Value=\u00226\u0022/\u003E\n \u003C/Style\u003E\n \u003C/VariableSizedWrapGrid.Resources\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Red\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Red\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Orange\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Orange\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Yellow\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Green\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Green\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Blue\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Blue\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Indigo\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Indigo\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Violet\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Violet\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003CButton Click=\u0022ColorButton_Click\u0022 AutomationProperties.Name=\u0022Gray\u0022\u003E\n \u003CButton.Content\u003E\n \u003CRectangle Fill=\u0022Gray\u0022/\u003E\n \u003C/Button.Content\u003E\n \u003C/Button\u003E\n \u003C/VariableSizedWrapGrid\u003E\n \u003C/Flyout\u003E\n \u003C/DropDownButton.Flyout\u003E\n \u003C/DropDownButton\u003E\n\n \u003CRichEditBox x:Name=\u0022editor\u0022 Height=\u0022200\u0022 AutomationProperties.Name=\u0022Custom editor\u0022\n RelativePanel.Below=\u0022openFileButton\u0022 \n RelativePanel.AlignLeftWithPanel=\u0022True\u0022 \n RelativePanel.AlignRightWithPanel=\u0022True\u0022 \n TextChanged=\u0022Editor_TextChanged\u0022\n GotFocus=\u0022Editor_GotFocus\u0022/\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022 \n RelativePanel.Below=\u0022editor\u0022 \n RelativePanel.AlignLeftWith=\u0022editor\u0022 \n Margin=\u00220,10,0,0\u0022\u003E\n \u003CTextBlock x:Name=\u0022findBoxLabel\u0022 Text=\u0022Find:\u0022 Height=\u002220\u0022/\u003E\n \u003CTextBox x:Name=\u0022findBox\u0022 Width=\u0022150\u0022 PlaceholderText=\u0022Enter search text\u0022 Margin=\u002210,0,0,0\u0022\n TextChanged=\u0022{x:Bind FindBoxHighlightMatches}\u0022 \n GotFocus=\u0022{x:Bind FindBoxHighlightMatches}\u0022 \n LostFocus=\u0022{x:Bind FindBoxRemoveHighlights}\u0022/\u003E\n \u003C/StackPanel\u003E\n\u003C/RelativePanel\u003E",
+ "code": "private async void OpenButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n // Create the picker using the AppWindowId from the element\n var picker = new FileOpenPicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId)\n {\n SuggestedStartLocation = PickerLocationId.DocumentsLibrary\n };\n\n // Add file type filters\n picker.FileTypeFilter.Add(\u0022.rtf\u0022);\n\n // Show picker\n PickFileResult result = await picker.PickSingleFileAsync();\n\n if (result != null)\n {\n // Open with StorageFile (needed for RichEditBox)\n StorageFile file = await StorageFile.GetFileFromPathAsync(result.Path);\n\n using IRandomAccessStream randAccStream =\n await file.OpenAsync(FileAccessMode.Read);\n\n // Load file into the RichEditBox\n editor.Document.LoadFromStream(TextSetOptions.FormatRtf, randAccStream);\n }\n }\n}\n\nprivate async void SaveButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n // Create the picker with AppWindowId\n var savePicker = new FileSavePicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId)\n {\n SuggestedStartLocation = PickerLocationId.DocumentsLibrary,\n SuggestedFileName = \u0022New Document\u0022\n };\n\n // Dropdown of file types the user can save the file as\n savePicker.FileTypeChoices.Add(\u0022Rich Text\u0022, new List\u003Cstring\u003E() { \u0022.rtf\u0022 });\n\n // Show picker\n PickFileResult result = await savePicker.PickSaveFileAsync();\n\n if (result != null)\n {\n // Convert PickSaveFileResult to StorageFile\n StorageFile file = await StorageFile.GetFileFromPathAsync(result.Path);\n\n // Prevent updates to the remote version of the file until complete\n CachedFileManager.DeferUpdates(file);\n\n // Write content into the file\n using IRandomAccessStream randAccStream =\n await file.OpenAsync(FileAccessMode.ReadWrite);\n\n editor.Document.SaveToStream(TextGetOptions.FormatRtf, randAccStream);\n\n // Finalize file updates\n FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);\n\n if (status != FileUpdateStatus.Complete)\n {\n var errorBox = new Windows.UI.Popups.MessageDialog(\n $\u0022File {file.Name} couldn\u0027t be saved.\u0022);\n await errorBox.ShowAsync();\n }\n }\n }\n}\n\nprivate void BoldButton_Click(object sender, RoutedEventArgs e)\n{\n editor.Document.Selection.CharacterFormat.Bold = FormatEffect.Toggle;\n}\n\nprivate void ItalicButton_Click(object sender, RoutedEventArgs e)\n{\n editor.Document.Selection.CharacterFormat.Italic = FormatEffect.Toggle;\n}\n\nprivate void ColorButton_Click(object sender, RoutedEventArgs e)\n{\n // Extract the color of the button that was clicked.\n Button clickedColor = (Button)sender;\n var rectangle = (Microsoft.UI.Xaml.Shapes.Rectangle)clickedColor.Content;\n var color = ((Microsoft.UI.Xaml.Media.SolidColorBrush)rectangle.Fill).Color;\n\n editor.Document.Selection.CharacterFormat.ForegroundColor = color;\n\n fontColorButton.Flyout.Hide();\n editor.Focus(Microsoft.UI.Xaml.FocusState.Keyboard);\n}\n\nprivate void FindBoxHighlightMatches()\n{\n FindBoxRemoveHighlights();\n\n Color highlightBackgroundColor = (Color)App.Current.Resources[\u0022SystemColorHighlightColor\u0022];\n Color highlightForegroundColor = (Color)App.Current.Resources[\u0022SystemColorHighlightTextColor\u0022];\n\n string textToFind = findBox.Text;\n if (textToFind != null)\n {\n ITextRange searchRange = editor.Document.GetRange(0, 0);\n while (searchRange.FindText(textToFind, TextConstants.MaxUnitCount, FindOptions.None) \u003E 0)\n {\n searchRange.CharacterFormat.BackgroundColor = highlightBackgroundColor;\n searchRange.CharacterFormat.ForegroundColor = highlightForegroundColor;\n }\n }\n}\n\nprivate void FindBoxRemoveHighlights()\n{\n if (editor.Background is not SolidColorBrush defaultBackground ||\n editor.Foreground is not SolidColorBrush defaultForeground)\n {\n return;\n }\n\n ITextRange documentRange = editor.Document.GetRange(0, TextConstants.MaxUnitCount);\n\n documentRange.CharacterFormat.BackgroundColor = defaultBackground.Color;\n documentRange.CharacterFormat.ForegroundColor = defaultForeground.Color;\n}\n\nprivate void Editor_GotFocus(object sender, RoutedEventArgs e)\n{\n editor.Document.GetText(TextGetOptions.UseCrlf, out _);\n \n // reset colors to correct defaults for Focused state\n ITextRange documentRange = editor.Document.GetRange(0, TextConstants.MaxUnitCount);\n SolidColorBrush background = (SolidColorBrush)App.Current.Resources[\u0022TextControlBackgroundFocused\u0022];\n\n if (background != null)\n {\n documentRange.CharacterFormat.BackgroundColor = background.Color;\n }\n}\n\nprivate void Editor_TextChanged(object sender, RoutedEventArgs e)\n{\n editor.Document.Selection.CharacterFormat.ForegroundColor = currentColor;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CustomEditorRicheditbox.txt",
+ "source": "WinUIGallery/Samples/RichEditBox/CustomEditorRicheditbox.txt",
+ "name": "Custom Editor Richeditbox"
+ }
+ },
+ {
+ "header": "Rich edit box in math mode",
+ "xaml": "\u003CRichEditBox x:Name=\u0022mathEditor\u0022 FontSize=\u002216\u0022 /\u003E",
+ "code": "mathEditor.TextDocument.SetMathMode(RichEditMathMode.MathOnly);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "RichEditBoxMath.txt",
+ "source": "WinUIGallery/Samples/RichEditBox/RichEditBoxMath.txt",
+ "name": "Math"
+ }
+ },
+ {
+ "header": "Working with MathML in RichEditBox",
+ "xaml": "\u003CRichEditBox x:Name=\u0022mathEditor2\u0022 FontSize=\u002216\u0022 /\u003E",
+ "code": "mathEditor2.TextDocument.SetMathMode(RichEditMathMode.MathOnly);\n\nprivate void mathEditor2_TextChanged(object sender, RoutedEventArgs e)\n{\n // Extracts the MathML content from the RichEditBox\n string extractedMathML;\n mathEditor2.Document.GetMathML(out extractedMathML);\n \n // If MathML content is available, format and display it in the MathML presenter\n if (!string.IsNullOrEmpty(extractedMathML))\n {\n MathmlPresenter.Code = MathModeHelper.FormatMathML(extractedMathML);\n }\n else\n {\n // If no MathML content exists, display a placeholder comment\n MathmlPresenter.Code = \u0022\u003C!-- No MathML content --\u003E\u0022;\n }\n}\n\nprivate void SetMathmlFormulaBtn_Click(object sender, RoutedEventArgs e)\n{\n // Defines a formula in MathML format\n string formulaMathML =\n \u0022\u003Cmml:math xmlns:mml=\\\u0022http://www.w3.org/1998/Math/MathML\\\u0022 display=\\\u0022block\\\u0022\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mi mathcolor=\\\u0022#000000\\\u0022\u003Ex\u003C/mml:mi\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mo mathcolor=\\\u0022#000000\\\u0022\u003E\\u2208\u003C/mml:mo\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mi mathcolor=\\\u0022#000000\\\u0022\u003EP\u003C/mml:mi\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mfenced\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mrow\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mi mathcolor=\\\u0022#000000\\\u0022\u003EA\u003C/mml:mi\u003E\\r\\n\u0022 \u002B\n \u0022 \u003C/mml:mrow\u003E\\r\\n\u0022 \u002B\n \u0022 \u003C/mml:mfenced\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mo mathcolor=\\\u0022#000000\\\u0022\u003E\\u2194\u003C/mml:mo\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mi mathcolor=\\\u0022#000000\\\u0022\u003Ex\u003C/mml:mi\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mo mathcolor=\\\u0022#000000\\\u0022\u003E\\u2286\u003C/mml:mo\u003E\\r\\n\u0022 \u002B\n \u0022 \u003Cmml:mi mathcolor=\\\u0022#000000\\\u0022\u003EA\u003C/mml:mi\u003E\\r\\n\u0022 \u002B\n \u0022\u003C/mml:math\u003E\u0022;\n\n // Adjusts text color based on the current app theme\n if(mathEditor2.ActualTheme == ElementTheme.Dark)\n {\n // If in dark mode, set text color to white\n mathEditor2.Document.SetMathML(formulaMathML.Replace(\u0022mathcolor=\\\u0022#000000\\\u0022\u0022, \u0022mathcolor=\\\u0022#FFFFFF\\\u0022\u0022));\n }\n else\n {\n // If in light mode, set text color to black\n mathEditor2.Document.SetMathML(formulaMathML.Replace(\u0022mathcolor=\\\u0022#FFFFFF\\\u0022\u0022, \u0022mathcolor=\\\u0022#000000\\\u0022\u0022));\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "WorkingMathmlRicheditbox.txt",
+ "source": "WinUIGallery/Samples/RichEditBox/WorkingMathmlRicheditbox.txt",
+ "name": "Working Mathml Richeditbox"
+ }
+ }
+ ]
+ },
+ {
+ "id": "richtextblock",
+ "name": "RichTextBlock",
+ "description": "A control that displays formatted text, hyperlinks, inline images, and other rich content.",
+ "details": "RichTextBlock provides more advanced formatting features than the TextBlock control. You can apply character and paragraph formatting to the text in the RichTextBlock. For example, you can apply Bold, Italic, and Underline to any portion of the text in the control. You can use linked text containers (a RichTextBlock linked to RichTextBlockOverflow elements) to create advanced page layouts.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NumberBox",
+ "TextBlock",
+ "TextBox",
+ "PasswordBox",
+ "RichEditBox"
+ ],
+ "usings": [
+ "Microsoft.UI",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Documents",
+ "Microsoft.UI.Xaml.Media"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "rich text",
+ "formatted text",
+ "inline content"
+ ],
+ "docs": [
+ {
+ "title": "RichTextBlock - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.richtextblock"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/text-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "RichTextBlock",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/RichTextBlock/RichTextBlockPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/RichTextBlock/RichTextBlockPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#NumberBox",
+ "microsoft/WinUI-Gallery#PasswordBox",
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#TextBlock",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple RichTextBlock.",
+ "xaml": "\u003CRichTextBlock\u003E\n \u003CParagraph\u003EI am a RichTextBlock.\u003C/Paragraph\u003E\n\u003C/RichTextBlock\u003E",
+ "gallery": {
+ "snippet": "SimpleRichtextblock.txt",
+ "source": "WinUIGallery/Samples/RichTextBlock/SimpleRichtextblock.txt",
+ "name": "Simple Richtextblock"
+ }
+ },
+ {
+ "header": "A RichTextBlock with a custom selection highlight color.",
+ "xaml": "\u003CRichTextBlock SelectionHighlightColor=\u0022Green\u0022\u003E\n \u003CParagraph\u003ERichTextBlock provides a rich text display container that supports\n \u003CRun FontStyle=\u0022Italic\u0022 FontWeight=\u0022Bold\u0022\u003Eformatted text\u003C/Run\u003E,\n \u003CHyperlink NavigateUri=\u0022https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Documents.Hyperlink\u0022\u003Ehyperlinks\u003C/Hyperlink\u003E, inline images, and other rich content.\u003C/Paragraph\u003E\n \u003CParagraph\u003ERichTextBlock also supports a built-in overflow model.\u003C/Paragraph\u003E\n\u003C/RichTextBlock\u003E",
+ "gallery": {
+ "snippet": "RichtextblockCustomSelectionHighlight.txt",
+ "source": "WinUIGallery/Samples/RichTextBlock/RichtextblockCustomSelectionHighlight.txt",
+ "name": "Custom Selection Highlight"
+ }
+ },
+ {
+ "header": "A RichTextBlock with overflow.",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition/\u003E\n \u003CColumnDefinition/\u003E\n \u003CColumnDefinition/\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003CRichTextBlock Grid.Column=\u00220\u0022 OverflowContentTarget=\u0022{x:Bind firstOverflowContainer}\u0022 TextAlignment=\u0022Justify\u0022 Margin=\u002212,0\u0022\u003E\n \u003CParagraph\u003E\n Linked text containers allow text which does not fit in one element to overflow into a different element on the page.\n Creative use of linked text containers enables basic multicolumn support and other advanced page layouts.\n \u003C/Paragraph\u003E\n \u003C!-- Additional content not shown. --\u003E\n \u003C/RichTextBlock\u003E\n \u003CRichTextBlockOverflow x:Name=\u0022firstOverflowContainer\u0022 OverflowContentTarget=\u0022{x:Bind secondOverflowContainer}\u0022 Grid.Column=\u00221\u0022 Margin=\u002212,0\u0022/\u003E\n \u003CRichTextBlockOverflow x:Name=\u0022secondOverflowContainer\u0022 Grid.Column=\u00222\u0022 Margin=\u002212,0\u0022/\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "RichtextblockOverflow.txt",
+ "source": "WinUIGallery/Samples/RichTextBlock/RichtextblockOverflow.txt",
+ "name": "Overflow"
+ }
+ },
+ {
+ "header": "RichTextBlock with custom TextHighlighting",
+ "xaml": "\u003CRichTextBlock x:Name=\u0022TextHighlightingRichTextBlock\u0022\u003E\n \u003CParagraph\u003E\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua\n \u003C/Paragraph\u003E\n\u003C/RichTextBlock\u003E",
+ "code": "private void HighlightColorCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e)\n{\n // Get color to use\n var selectedItem = (sender as ComboBox).SelectedItem as ComboBoxItem;\n var color = Colors.Yellow;\n switch (selectedItem.Content as string)\n {\n case \u0022Yellow\u0022:\n color = Colors.Yellow;\n break;\n case \u0022Red\u0022:\n color = Colors.Red;\n break;\n case \u0022Blue\u0022:\n color = Colors.Blue;\n break;\n }\n\n // Get text range and highlighter\n TextRange textRange = new TextRange()\n {\n StartIndex = 28,\n Length = 11\n };\n TextHighlighter highlighter = new TextHighlighter()\n {\n Background = new SolidColorBrush(color),\n Ranges = { textRange }\n };\n\n // Switch texthighlighter\n TextHighlightingRichTextBlock.TextHighlighters.Clear();\n TextHighlightingRichTextBlock.TextHighlighters.Add(highlighter);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "RichtextblockCustomTexthighlighting.txt",
+ "source": "WinUIGallery/Samples/RichTextBlock/RichtextblockCustomTexthighlighting.txt",
+ "name": "Custom Texthighlighting"
+ }
+ }
+ ]
+ },
+ {
+ "id": "scratchpad",
+ "name": "Scratch Pad",
+ "description": "Scratch pad for testing simple XAML markup",
+ "details": "Provides an edit box where you can type in some markup and load it to see how it looks and behaves.",
+ "curatedKeywords": [
+ "playground",
+ "sandbox",
+ "test markup",
+ "repl",
+ "live xaml preview"
+ ],
+ "docs": [
+ {
+ "title": "XamlReader - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.markup.xamlreader"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ScratchPad",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/ScratchPad/ScratchPadPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ScratchPad/ScratchPadPage.xaml.cs"
+ },
+ "samples": []
+ },
+ {
+ "id": "scrollview",
+ "name": "ScrollView",
+ "description": "A container control that lets the user pan and zoom its content.",
+ "details": "A ScrollView lets a user scroll, pan, and zoom to see content that\u0027s larger than the viewable area. The ItemsView has a ScrollView built into its control template to provide automatic scrolling.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Viewbox",
+ "Canvas",
+ "Grid",
+ "StackPanel",
+ "RelativePanel",
+ "ParallaxView",
+ "ItemsView",
+ "ScrollViewer"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "pan",
+ "zoom",
+ "scrolling"
+ ],
+ "docs": [
+ {
+ "title": "ScrollView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.scrollview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/scroll-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ScrollView",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/ScrollView/ScrollViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ScrollView/ScrollViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#ItemsView",
+ "microsoft/WinUI-Gallery#ParallaxView",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#ScrollViewer",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#Viewbox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Content inside of a ScrollView.",
+ "xaml": "\u003CScrollView Height=\u0022266\u0022 Width=\u0022400\u0022 ContentOrientation=\u0022None\u0022\n ZoomMode=\u0022Enabled\u0022 IsTabStop=\u0022True\u0022\n VerticalAlignment=\u0022Top\u0022 HorizontalAlignment=\u0022Left\u0022\n HorizontalScrollMode=\u0022Auto\u0022 HorizontalScrollBarVisibility=\u0022Auto\u0022\n VerticalScrollMode=\u0022Auto\u0022 VerticalScrollBarVisibility=\u0022Auto\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 AutomationProperties.Name=\u0022cliff\u0022 Stretch=\u0022None\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n\u003C/ScrollView\u003E",
+ "gallery": {
+ "snippet": "ContentInsideScrollview.txt",
+ "source": "WinUIGallery/Samples/ScrollView/ContentInsideScrollview.txt",
+ "name": "Content Inside Scrollview"
+ }
+ },
+ {
+ "header": "Constant velocity scrolling.",
+ "xaml": "\u003CScrollView Height=\u0022300\u0022 Width=\u0022400\u0022 IsTabStop=\u0022True\u0022\n VerticalAlignment=\u0022Top\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/grapes.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022grapes\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/rainier.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022rainier\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/sunset.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022sunset\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/treetops.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022treetops\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/valley.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022valley\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022cliff\u0022/\u003E\n\u003C/ScrollView\u003E",
+ "gallery": {
+ "snippet": "ScrollViewConstantVelocityScrolling.txt",
+ "source": "WinUIGallery/Samples/ScrollView/ScrollViewConstantVelocityScrolling.txt",
+ "name": "Constant Velocity Scrolling"
+ }
+ },
+ {
+ "header": "Programmatic scroll with custom animation.",
+ "xaml": "\u003CScrollView Height=\u0022300\u0022 Width=\u0022400\u0022 IsTabStop=\u0022True\u0022\n ScrollAnimationStarting=\u0022ScrollView_ScrollAnimationStarting\u0022\n VerticalAlignment=\u0022Top\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage1.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022leaves\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage2.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022carousel\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage3.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022bicycles\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage4.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022pond\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage5.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022marina\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage6.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022beach\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage7.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022rampart\u0022/\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/LandscapeImage8.jpg\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022mountain\u0022/\u003E\n\u003C/ScrollView\u003E",
+ "gallery": {
+ "snippet": "ScrollViewProgrammaticScrollCustomAnimation.txt",
+ "source": "WinUIGallery/Samples/ScrollView/ScrollViewProgrammaticScrollCustomAnimation.txt",
+ "name": "Programmatic Scroll Custom Animation"
+ }
+ }
+ ]
+ },
+ {
+ "id": "scrollviewer",
+ "name": "ScrollViewer",
+ "description": "A container control that lets the user pan and zoom its content.",
+ "details": "A ScrollViewer lets a user scroll, pan, and zoom to see content that\u0027s larger than the viewable area. Many content controls, like ListView, have ScrollViewers built into their control templates to provide automatic scrolling.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Viewbox",
+ "Canvas",
+ "Grid",
+ "StackPanel",
+ "RelativePanel",
+ "ParallaxView",
+ "ScrollView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "pan",
+ "zoom",
+ "scrolling"
+ ],
+ "docs": [
+ {
+ "title": "ScrollViewer - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.scrollviewer"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/scroll-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ScrollViewer",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/ScrollViewer/ScrollViewerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ScrollViewer/ScrollViewerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#ParallaxView",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#ScrollView",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#Viewbox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Content inside of a ScrollViewer.",
+ "xaml": "\u003CScrollViewer Height=\u0022266\u0022 Width=\u0022400\u0022 ZoomMode=\u0022Enabled\u0022\n IsTabStop=\u0022True\u0022 IsVerticalScrollChainingEnabled=\u0022True\u0022\n HorizontalAlignment=\u0022Left\u0022 VerticalAlignment=\u0022Top\u0022\n ViewChanged=\u0022ScrollViewerControl_ViewChanged\u0022\n HorizontalScrollMode=\u0022Enabled\u0022 HorizontalScrollBarVisibility=\u0022Auto\u0022\n VerticalScrollMode=\u0022Enabled\u0022 VerticalScrollBarVisibility=\u0022Auto\u0022\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/cliff.jpg\u0022 AutomationProperties.Name=\u0022cliff\u0022 Stretch=\u0022None\u0022\n HorizontalAlignment=\u0022Left\u0022 VerticalAlignment=\u0022Top\u0022/\u003E\n\u003C/ScrollViewer\u003E",
+ "gallery": {
+ "snippet": "ContentInsideScrollviewer.txt",
+ "source": "WinUIGallery/Samples/ScrollViewer/ContentInsideScrollviewer.txt",
+ "name": "Content Inside Scrollviewer"
+ }
+ }
+ ]
+ },
+ {
+ "id": "selectorbar",
+ "name": "SelectorBar",
+ "description": "Presents information from a small set of different sources. The user can pick one of them.",
+ "details": "SelectorBar is used to modify the content shown by allowing users to select and switch between a small, finite set of data.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NavigationView",
+ "PipsPager",
+ "Pivot"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media",
+ "Microsoft.UI.Xaml.Media.Animation",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "segmented",
+ "tabs"
+ ],
+ "docs": [
+ {
+ "title": "SelectorBar - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.selectorbar"
+ },
+ {
+ "title": "SelectorBarItem - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.selectorbaritem"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SelectorBar",
+ "group": {
+ "id": "Navigation",
+ "title": "Navigation"
+ },
+ "page": "WinUIGallery/Samples/SelectorBar/SelectorBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SelectorBar/SelectorBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#NavigationView",
+ "microsoft/WinUI-Gallery#PipsPager",
+ "microsoft/WinUI-Gallery#Pivot"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A Basic SelectorBar",
+ "xaml": "\u003CSelectorBar x:Name=\u0022SelectorBar1\u0022\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemRecent\u0022 Text=\u0022Recent\u0022 Icon=\u0022Clock\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemShared\u0022 Text=\u0022Shared\u0022 Icon=\u0022Share\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemFavorites\u0022 Text=\u0022Favorites\u0022 Icon=\u0022Favorite\u0022 /\u003E\n\u003C/SelectorBar\u003E",
+ "gallery": {
+ "snippet": "BasicSelectorbar.txt",
+ "source": "WinUIGallery/Samples/SelectorBar/BasicSelectorbar.txt",
+ "name": "Basic Selectorbar"
+ }
+ },
+ {
+ "header": "SelectorBar with Frame Slide Transitions",
+ "xaml": "\u003CSelectorBar x:Name=\u0022SelectorBar2\u0022 SelectionChanged=\u0022SelectorBar2_SelectionChanged\u0022\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPage1\u0022 Text=\u0022Page1\u0022 IsSelected=\u0022True\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPage2\u0022 Text=\u0022Page2\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPage3\u0022 Text=\u0022Page3\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPage4\u0022 Text=\u0022Page4\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPage5\u0022 Text=\u0022Page5\u0022 /\u003E\n\u003C/SelectorBar\u003E\n\n\u003CFrame x:Name=\u0022ContentFrame\u0022 IsNavigationStackEnabled=\u0022False\u0022 /\u003E",
+ "code": "private void SelectorBar2_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)\n {\n SelectorBarItem selectedItem = sender.SelectedItem;\n int currentSelectedIndex = sender.Items.IndexOf(selectedItem);\n System.Type pageType;\n\n switch (currentSelectedIndex)\n {\n case 0:\n pageType = typeof(SamplePage1);\n break;\n case 1:\n pageType = typeof(SamplePage2);\n break;\n case 2:\n pageType = typeof(SamplePage3);\n break;\n case 3:\n pageType = typeof(SamplePage4);\n break;\n default:\n pageType = typeof(SamplePage5);\n break;\n }\n\n var slideNavigationTransitionEffect = currentSelectedIndex - previousSelectedIndex \u003E 0 ? SlideNavigationTransitionEffect.FromRight : SlideNavigationTransitionEffect.FromLeft;\n\n ContentFrame.Navigate(pageType, null, new SlideNavigationTransitionInfo() { Effect = slideNavigationTransitionEffect });\n\n previousSelectedIndex = currentSelectedIndex;\n }",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SelectorbarFrameSlideTransitions.txt",
+ "source": "WinUIGallery/Samples/SelectorBar/SelectorbarFrameSlideTransitions.txt",
+ "name": "Frame Slide Transitions"
+ }
+ },
+ {
+ "header": "SelectorBar Displaying Different Collections Using ItemsView",
+ "xaml": "\u003CSelectorBar x:Name=\u0022SelectorBar3\u0022 SelectionChanged=\u0022SelectorBar3_SelectionChanged\u0022 \u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPink\u0022 Text=\u0022Pink\u0022 IsSelected=\u0022True\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPlum\u0022 Text=\u0022Plum\u0022 /\u003E\n \u003CSelectorBarItem x:Name=\u0022SelectorBarItemPowderBlue\u0022 Text=\u0022PowderBlue\u0022 /\u003E\n\u003C/SelectorBar\u003E\n\n\u003CItemsView x:Name=\u0022ItemsView3\u0022 ItemTemplate=\u0022{StaticResource ColorsTemplate}\u0022\u003E\n \u003CItemsView.Layout\u003E\n \u003CUniformGridLayout /\u003E\n \u003C/ItemsView.Layout\u003E\n\u003C/ItemsView\u003E",
+ "code": "private void SelectorBar3_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args)\n{\n if (sender.SelectedItem == SelectorBarItemPink)\n {\n ItemsView3.ItemsSource = PinkColorCollection;\n }\n else if (sender.SelectedItem == SelectorBarItemPlum)\n {\n ItemsView3.ItemsSource = PlumColorCollection;\n }\n else\n {\n ItemsView3.ItemsSource = PowderBlueColorCollection;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SelectorbarDisplayingDifferentCollections.txt",
+ "source": "WinUIGallery/Samples/SelectorBar/SelectorbarDisplayingDifferentCollections.txt",
+ "name": "Displaying Different Collections"
+ }
+ }
+ ]
+ },
+ {
+ "id": "semanticzoom",
+ "name": "SemanticZoom",
+ "description": "Lets the user zoom between two different views of a collection, making it easier to navigate through large collections of items.",
+ "details": "The SemanticZoom lets you show grouped data in two different ways, and is useful for quickly navigating through large sets of data.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "GridView",
+ "ListView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "semantic zoom",
+ "grouped view"
+ ],
+ "docs": [
+ {
+ "title": "SemanticZoom - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.semanticzoom"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/semantic-zoom"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SemanticZoom",
+ "group": {
+ "id": "Scrolling",
+ "title": "Scrolling"
+ },
+ "page": "WinUIGallery/Samples/SemanticZoom/SemanticZoomPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SemanticZoom/SemanticZoomPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ListView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple SemanticZoom",
+ "xaml": "\u003CSemanticZoom Height=\u0022500\u0022\u003E\n \u003CSemanticZoom.ZoomedInView\u003E\n \u003CGridView ItemsSource=\u0022{x:Bind cvsGroups.View}\u0022 SelectionMode=\u0022None\u0022\n ItemTemplate=\u0022{StaticResource ZoomedInTemplate}\u0022\u003E\n \u003CGridView.GroupStyle\u003E\n \u003CGroupStyle HeaderTemplate=\u0022{StaticResource ZoomedInGroupHeaderTemplate}\u0022 /\u003E\n \u003C/GridView.GroupStyle\u003E\n \u003C/GridView\u003E\n \u003C/SemanticZoom.ZoomedInView\u003E\n\n \u003CSemanticZoom.ZoomedOutView\u003E\n \u003CListView ItemsSource=\u0022{x:Bind cvsGroups.View.CollectionGroups}\u0022 HorizontalAlignment=\u0022Stretch\u0022\n SelectionMode=\u0022None\u0022 ItemTemplate=\u0022{StaticResource ZoomedOutTemplate}\u0022 /\u003E\n \u003C/SemanticZoom.ZoomedOutView\u003E\n\u003C/SemanticZoom\u003E",
+ "gallery": {
+ "snippet": "SimpleSemanticzoom.txt",
+ "source": "WinUIGallery/Samples/SemanticZoom/SimpleSemanticzoom.txt",
+ "name": "Simple Semanticzoom"
+ }
+ }
+ ]
+ },
+ {
+ "id": "shape",
+ "name": "Shape",
+ "description": "How to draw shapes, such as ellipses, rectangles, and polygons.",
+ "details": "Basic shapes are intended for decorative rendering or for compositing non-interactive parts of controls.",
+ "apiNamespace": "Microsoft.UI.Xaml.Shapes",
+ "relatedControls": [
+ "Line"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "shapes",
+ "ellipse",
+ "rectangle",
+ "polygon",
+ "path",
+ "circle"
+ ],
+ "docs": [
+ {
+ "title": "Shapes - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.shapes"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/previous-versions/windows/apps/hh465055(v=win.10)"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Shape",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/Shape/ShapePage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Shape/ShapePage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Line"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Ellipse",
+ "xaml": "\u003CEllipse Fill=\u0022SteelBlue\u0022 Stroke=\u0022Black\u0022/\u003E",
+ "gallery": {
+ "snippet": "ShapeEllipse.txt",
+ "source": "WinUIGallery/Samples/Shape/ShapeEllipse.txt",
+ "name": "Ellipse",
+ "xamlPlaceholdersDropped": [
+ "Slider1",
+ "Slider2",
+ "Slider3"
+ ]
+ }
+ },
+ {
+ "header": "Rectangle",
+ "xaml": "\u003CRectangle Fill=\u0022SteelBlue\u0022\n Stroke=\u0022Black\u0022/\u003E",
+ "gallery": {
+ "snippet": "ShapeRectangle.txt",
+ "source": "WinUIGallery/Samples/Shape/ShapeRectangle.txt",
+ "name": "Rectangle",
+ "xamlPlaceholdersDropped": [
+ "Slider1",
+ "Slider2",
+ "Slider3",
+ "Slider4",
+ "Slider5"
+ ]
+ }
+ },
+ {
+ "header": "Polygon",
+ "xaml": "\u003CPolygon Fill=\u0022SteelBlue\u0022 Points=\u002210,100 60,40 200,40 250,100\u0022 Stroke=\u0022Black\u0022/\u003E",
+ "gallery": {
+ "snippet": "ShapePolygon.txt",
+ "source": "WinUIGallery/Samples/Shape/ShapePolygon.txt",
+ "name": "Polygon",
+ "xamlPlaceholdersDropped": [
+ "Slider1"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "slider",
+ "name": "Slider",
+ "description": "A control that lets the user select from a range of values by moving a Thumb control along a track.",
+ "details": "Use a Slider when you want your users to be able to set defined, contiguous values (such as volume or brightness) or a range of discrete values (such as screen resolution settings).",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ComboBox",
+ "RatingControl"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "RangeBase"
+ ],
+ "curatedKeywords": [
+ "range",
+ "track",
+ "Thumb"
+ ],
+ "docs": [
+ {
+ "title": "Slider - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.slider"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/slider"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Slider",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/Slider/SliderPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Slider/SliderPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "RangeBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ComboBox",
+ "microsoft/WinUI-Gallery#RatingControl"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple Slider.",
+ "xaml": "\u003CSlider AutomationProperties.Name=\u0022simple slider\u0022 Width=\u0022200\u0022/\u003E",
+ "gallery": {
+ "snippet": "SliderSimple.txt",
+ "source": "WinUIGallery/Samples/Slider/SliderSimple.txt",
+ "name": "Simple"
+ }
+ },
+ {
+ "header": "A Slider with range and steps specified.",
+ "xaml": "\u003CSlider Width=\u0022200\u0022 Minimum=\u0022500\u0022 Maximum=\u00221000\u0022 StepFrequency=\u002210\u0022\n SmallChange=\u002210\u0022 Value=\u0022800\u0022 /\u003E",
+ "gallery": {
+ "snippet": "SliderRange.txt",
+ "source": "WinUIGallery/Samples/Slider/SliderRange.txt",
+ "name": "Range"
+ }
+ },
+ {
+ "header": "A Slider with tick marks.",
+ "xaml": "\u003CSlider\n AutomationProperties.Name=\u0022Slider with ticks\u0022\n TickFrequency=\u002220\u0022\n TickPlacement=\u0022Outside\u0022\n SnapsTo=\u0022StepValues\u0022 /\u003E",
+ "gallery": {
+ "snippet": "SliderTicks.txt",
+ "source": "WinUIGallery/Samples/Slider/SliderTicks.txt",
+ "name": "Ticks"
+ }
+ },
+ {
+ "header": "A vertical slider with range and tick marks specified.",
+ "xaml": "\u003CSlider AutomationProperties.Name=\u0022vertical slider\u0022 Width=\u0022100\u0022 Orientation=\u0022Vertical\u0022\n TickFrequency=\u002210\u0022 TickPlacement=\u0022Outside\u0022 Maximum=\u002250\u0022 Minimum=\u0022-50\u0022/\u003E",
+ "gallery": {
+ "snippet": "SliderVertical.txt",
+ "source": "WinUIGallery/Samples/Slider/SliderVertical.txt",
+ "name": "Vertical"
+ }
+ }
+ ]
+ },
+ {
+ "id": "sound",
+ "name": "Sound",
+ "description": "A code-behind only API that enables 2D and 3D UI sounds on all XAML controls.",
+ "details": "Sound is enabled by default for UWP apps running on Xbox, but can be set to always play on all devices if desired. Sound may also be put into Spatial Audio mode for a more immersive 10ft experience.",
+ "apiNamespace": "Microsoft.UI.Xaml",
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "curatedKeywords": [
+ "audio",
+ "UI sound",
+ "ElementSoundPlayer"
+ ],
+ "docs": [
+ {
+ "title": "Sound - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.elementsoundplayer"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/sound"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Sound",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/Sound/SoundPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Sound/SoundPage.xaml.cs"
+ },
+ "samples": [
+ {
+ "header": "Toggling Sound",
+ "code": "ElementSoundPlayer.State = ElementSoundPlayerState.Off;\nElementSoundPlayer.State = ElementSoundPlayerState.On;",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TogglingSound.txt",
+ "source": "WinUIGallery/Samples/Sound/TogglingSound.txt",
+ "name": "Toggling Sound"
+ }
+ },
+ {
+ "header": "Toggling Spatial Audio",
+ "code": "ElementSoundPlayer.State = ElementSoundPlayerState.On;\nElementSoundPlayer.SpatialAudioMode = ElementSpatialAudioMode.On",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SoundTogglingSpatialAudio.txt",
+ "source": "WinUIGallery/Samples/Sound/SoundTogglingSpatialAudio.txt",
+ "name": "Toggling Spatial Audio"
+ }
+ },
+ {
+ "header": "Play Specific System Sound",
+ "code": "ElementSoundPlayer.State = ElementSoundPlayerState.On;\n\nElementSoundPlayer.Play(ElementSoundKind.Focus);\nElementSoundPlayer.Play(ElementSoundKind.Invoke);\nElementSoundPlayer.Play(ElementSoundKind.Show);\nElementSoundPlayer.Play(ElementSoundKind.Hide);\nElementSoundPlayer.Play(ElementSoundKind.MovePrevious);\nElementSoundPlayer.Play(ElementSoundKind.MoveNext);\nElementSoundPlayer.Play(ElementSoundKind.GoBack);",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "PlaySpecificSystemSound.txt",
+ "source": "WinUIGallery/Samples/Sound/PlaySpecificSystemSound.txt",
+ "name": "Play Specific System Sound"
+ }
+ }
+ ]
+ },
+ {
+ "id": "spacing",
+ "name": "Spacing",
+ "description": "Thoughtful spacing design enhances readability and flow.",
+ "curatedKeywords": [
+ "margin",
+ "padding",
+ "layout spacing"
+ ],
+ "docs": [
+ {
+ "title": "Content design basics",
+ "uri": "https://learn.microsoft.com/windows/apps/design/basics/content-basics"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Spacing",
+ "group": {
+ "id": "DesignItem",
+ "title": "Design"
+ },
+ "page": "WinUIGallery/Samples/Spacing/SpacingPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Spacing/SpacingPage.xaml.cs"
+ },
+ "samples": []
+ },
+ {
+ "id": "splitbutton",
+ "name": "SplitButton",
+ "description": "A two-part button that displays a flyout when its secondary part is clicked.",
+ "details": "The SplitButton is a dropdown button, but with an addition execution hit target.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Button",
+ "DropDownButton",
+ "ToggleSplitButton",
+ "AppBarButton",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "split",
+ "dropdown button"
+ ],
+ "docs": [
+ {
+ "title": "SplitButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.splitbutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons#create-a-split-button"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SplitButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/SplitButton/SplitButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SplitButton/SplitButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#DropDownButton",
+ "microsoft/WinUI-Gallery#ToggleSplitButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A SplitButton controlling text color in a RichEditBox",
+ "xaml": "\u003CSplitButton x:Name=\u0022myColorButton\u0022 Click=\u0022myColorButton_Click\u0022\u003E\n \u003CBorder x:Name=\u0022CurrentColor\u0022 Width=\u002232\u0022 Height=\u002232\u0022 Background=\u0022Green\u0022 CornerRadius=\u00224,0,0,4\u0022/\u003E\n \u003CSplitButton.Flyout\u003E\n \u003CFlyout Placement=\u0022Bottom\u0022\u003E\n \u003C!-- flyout content --\u003E\n \u003C/Flyout\u003E\n \u003C/SplitButton.Flyout\u003E\n\u003C/SplitButton\u003E",
+ "gallery": {
+ "snippet": "SplitButtonColorPicker.txt",
+ "source": "WinUIGallery/Samples/SplitButton/SplitButtonColorPicker.txt",
+ "name": "Color Picker"
+ }
+ },
+ {
+ "header": "A SplitButton with text",
+ "xaml": "\u003CSplitButton x:Name=\u0022myColorButton\u0022\u003E\n Choose color\n \u003CSplitButton.Flyout\u003E\n \u003CFlyout Placement=\u0022Bottom\u0022\u003E\n \u003C!-- flyout content --\u003E\n \u003C/Flyout\u003E\n \u003C/SplitButton.Flyout\u003E\n\u003C/SplitButton\u003E",
+ "gallery": {
+ "snippet": "SplitButtonText.txt",
+ "source": "WinUIGallery/Samples/SplitButton/SplitButtonText.txt",
+ "name": "Text"
+ }
+ }
+ ]
+ },
+ {
+ "id": "splitview",
+ "name": "SplitView",
+ "description": "A container that has 2 content areas, with multiple display options for the pane.",
+ "details": "Use a SplitView to display content, such as navigation options, in a pane on the side. There are multiple options for displaying the pane, namely CompactOverlay, Compact, Overlay, Inline. If you are looking for a hamburger navigation pattern, check out the NavigationView sample.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "StackPanel",
+ "ListView",
+ "GridView",
+ "Grid",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "pane",
+ "hamburger",
+ "navigation pane"
+ ],
+ "docs": [
+ {
+ "title": "SplitView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.splitview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/split-view"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SplitView",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/SplitView/SplitViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SplitView/SplitViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#StackPanel"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A basic SplitView.",
+ "xaml": "\u003CSplitView x:Name=\u0022splitView\u0022 PaneBackground=\u0022{}{ThemeResource SystemControlBackgroundChromeMediumLowBrush}\u0022\n IsPaneOpen=\u0022{x:Bind togglePaneButton.IsChecked, Mode=TwoWay, Converter={StaticResource nullableBooleanToBooleanConverter}}\u0022 OpenPaneLength=\u0022256\u0022 CompactPaneLength=\u002248\u0022 DisplayMode=\u0022CompactOverlay\u0022\u003E\n \u003CSplitView.Pane\u003E\n \u003CGrid\u003E\n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CTextBlock Text=\u0022PANE CONTENT\u0022 x:Name=\u0022PaneHeader\u0022 Margin=\u002260,12,0,0\u0022 Style=\u0022{StaticResource BaseTextBlockStyle}\u0022/\u003E\n \u003CListView x:Name=\u0022NavLinksList\u0022 Margin=\u00220,12,0,0\u0022 SelectionMode=\u0022Single\u0022 Grid.Row=\u00221\u0022 VerticalAlignment=\u0022Stretch\u0022\n ItemClick=\u0022NavLinksList_ItemClick\u0022 IsItemClickEnabled=\u0022True\u0022\n ItemsSource=\u0022{x:Bind NavLinks}\u0022 ItemTemplate=\u0022{StaticResource NavLinkItemTemplate}\u0022/\u003E\n \u003C/Grid\u003E\n \u003C/SplitView.Pane\u003E\n \n \u003CGrid\u003E\n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022Auto\u0022/\u003E\n \u003CRowDefinition Height=\u0022*\u0022/\u003E\n \u003C/Grid.RowDefinitions\u003E\n \u003CTextBlock Text=\u0022SPLITVIEW CONTENT\u0022 Margin=\u002212,12,0,0\u0022 Style=\u0022{StaticResource BaseTextBlockStyle}\u0022/\u003E\n \u003CTextBlock x:Name=\u0022content\u0022 Grid.Row=\u00221\u0022 Margin=\u002212,12,0,0\u0022 Style=\u0022{StaticResource BodyTextBlockStyle}\u0022 /\u003E\n \u003C/Grid\u003E\n\u003C/SplitView\u003E",
+ "gallery": {
+ "snippet": "BasicSplitview.txt",
+ "source": "WinUIGallery/Samples/SplitView/BasicSplitview.txt",
+ "name": "Basic Splitview"
+ }
+ }
+ ]
+ },
+ {
+ "id": "stackpanel",
+ "name": "StackPanel",
+ "description": "A layout panel that arranges child elements into a single line that can be oriented horizontally or vertically.",
+ "details": "A StackPanel is used to arrange items in a line, either horizontally or vertically.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Border",
+ "Canvas",
+ "Grid",
+ "VariableSizedWrapGrid",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "stack",
+ "vertical layout",
+ "horizontal layout"
+ ],
+ "docs": [
+ {
+ "title": "StackPanel - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.stackpanel"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/layout-panels"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "StackPanel",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/StackPanel/StackPanelPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/StackPanel/StackPanelPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Border",
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#VariableSizedWrapGrid"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A StackPanel control.",
+ "xaml": "\u003CStackPanel\n Spacing=\u0022{x:Bind SpacingSlider.Value, Mode=OneWay}\u0022\u003E\n \u003CRectangle Fill=\u0022Red\u0022/\u003E\n \u003CRectangle Fill=\u0022Blue\u0022/\u003E\n \u003CRectangle Fill=\u0022Green\u0022/\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "StackpanelControl.txt",
+ "source": "WinUIGallery/Samples/StackPanel/StackpanelControl.txt",
+ "name": "Control",
+ "xamlPlaceholdersDropped": [
+ "Orientation"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "standarduicommand",
+ "name": "StandardUICommand",
+ "description": "A StandardUICommand is a built-in \u0027XamlUICommand\u0027 which represents a commonly used command, e.g. \u0027Save\u0027.",
+ "details": "StandardUICommands are a set of built-in XamlUICommands represeting commonly used commands. Including the look and feel of a given command, which can be reused across your app, and which is understood natively by the standard XAML controls. E.g. Save, Open, Copy, Paste, etc.",
+ "apiNamespace": "Microsoft.UI.Xaml.Input",
+ "relatedControls": [
+ "XamlUICommand",
+ "AppBarButton",
+ "AppBarToggleButton",
+ "CommandBar"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Input",
+ "System.Collections.ObjectModel",
+ "Windows.Foundation.Metadata"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "XamlUICommand"
+ ],
+ "curatedKeywords": [
+ "standard command"
+ ],
+ "docs": [
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/commanding#command-experiences-using-the-standarduicommand-class"
+ },
+ {
+ "title": "StandardUICommand - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.input.standarduicommand"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "StandardUICommand",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/StandardUICommand/StandardUICommandPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/StandardUICommand/StandardUICommandPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "XamlUICommand"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#XamlUICommand"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Exposing a command in multiple controls using StandardUICommand",
+ "xaml": "\u003CSwipeItem x:Name=\u0022DeleteSwipeItem\u0022 Background=\u0022Red\u0022 Command=\u0022{x:Bind Command}\u0022 CommandParameter=\u0022{x:Bind Text}\u0022 /\u003E\n\n\u003CAppBarButton x:Name=\u0022HoverButton\u0022 IsTabStop=\u0022False\u0022 HorizontalAlignment=\u0022Right\u0022 Visibility=\u0022Collapsed\u0022 \n Command=\u0022{x:Bind Command}\u0022 CommandParameter=\u0022{x:Bind Text}\u0022 /\u003E",
+ "code": "private void ControlExample_Loaded(object sender, RoutedEventArgs e)\n{\n var deleteCommand = new StandardUICommand(StandardUICommandKind.Delete);\n deleteCommand.ExecuteRequested \u002B= DeleteCommand_ExecuteRequested;\n\n DeleteFlyoutItem.Command = deleteCommand;\n\n for (var i = 0; i \u003C 15; i\u002B\u002B)\n {\n collection.Add(new ListItemData { Text = \u0022List item \u0022 \u002B i.ToString(), Command = deleteCommand });\n }\n}\n\nprivate void ListViewRight_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)\n{\n MenuFlyout flyout = new MenuFlyout();\n ListItemData data = (ListItemData)args.Item;\n MenuFlyoutItem item = new MenuFlyoutItem() { Command = data.Command};\n flyout.Items.Add(item);\n args.ItemContainer.ContextFlyout = flyout;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StandardUICommandExposingCommandMultipleControls.txt",
+ "source": "WinUIGallery/Samples/StandardUICommand/StandardUICommandExposingCommandMultipleControls.txt",
+ "name": "Exposing Command Multiple Controls"
+ }
+ }
+ ]
+ },
+ {
+ "id": "storagepickers",
+ "name": "Storage pickers",
+ "description": "Select files and folders with modern system pickers.",
+ "details": "Use the FileOpenPicker, FileSavePicker, and FolderPicker APIs to let users select files and folders in a secure way.",
+ "apiNamespace": "Microsoft.Windows.Storage.Pickers",
+ "relatedControls": [
+ "Clipboard"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media.Imaging",
+ "Microsoft.Windows.Storage.Pickers",
+ "System",
+ "System.Collections.Generic",
+ "System.IO",
+ "Windows.Storage",
+ "Windows.Storage.FileProperties"
+ ],
+ "keywords": [
+ "Object"
+ ],
+ "curatedKeywords": [
+ "file picker",
+ "FileOpenPicker",
+ "FileSavePicker",
+ "FolderPicker",
+ "file dialog"
+ ],
+ "docs": [
+ {
+ "title": "FileOpenPicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.storage.pickers.fileopenpicker"
+ },
+ {
+ "title": "FileSavePicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.storage.pickers.filesavepicker"
+ },
+ {
+ "title": "FolderPicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.windows.storage.pickers.folderpicker"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "StoragePickers",
+ "group": {
+ "id": "System",
+ "title": "System"
+ },
+ "page": "WinUIGallery/Samples/StoragePickers/StoragePickersPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/StoragePickers/StoragePickersPage.xaml.cs",
+ "baseClasses": [
+ "Object"
+ ],
+ "badges": [
+ "Updated"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Clipboard"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Pick single file",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CButton x:Name=\u0022PickSingleFileButton\u0022 Content=\u0022Pick a single file\u0022 Click=\u0022PickSingleFileButton_Click\u0022/\u003E\n \u003CTextBlock x:Name=\u0022PickedSingleFileTextBlock\u0022 Text=\u0022No file picked\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "code": "private async void PickSingleFileButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n //disable the button to avoid double-clicking\n button.IsEnabled = false;\n\n var picker = new FileOpenPicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId);$(FileType)\n\n picker.CommitButtonText = \u0022Pick File\u0022;\n\n picker.SuggestedStartLocation = PickerLocationId.$(SuggestedStartLocation);\n\n picker.ViewMode = PickerViewMode.$(ViewMode);\n\n // Show the picker dialog window\n var file = await picker.PickSingleFileAsync();\n PickedSingleFileTextBlock.Text = file != null\n ? \u0022Picked: \u0022 \u002B file.Path\n : \u0022No file selected.\u0022;\n\n //re-enable the button\n button.IsEnabled = true;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StoragePickersPickSingleFile.txt",
+ "source": "WinUIGallery/Samples/StoragePickers/StoragePickersPickSingleFile.txt",
+ "name": "Pick Single File",
+ "codePlaceholdersPresent": [
+ "FileType",
+ "SuggestedStartLocation",
+ "ViewMode"
+ ]
+ }
+ },
+ {
+ "header": "Pick multiple files",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CButton x:Name=\u0022PickMultipleFilesButton\u0022 Content=\u0022Pick multiple files\u0022 Click=\u0022PickMultipleFilesButton_Click\u0022/\u003E\n \u003CTextBlock x:Name=\u0022PickedMultipleFilesTextBlock\u0022 Text=\u0022No files picked\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "code": "private async void PickMultipleFilesButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n //disable the button to avoid double-clicking\n button.IsEnabled = false;\n\n var picker = new FileOpenPicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId);$(FileType)\n \n picker.CommitButtonText = \u0022Pick Files\u0022;\n \n picker.SuggestedStartLocation = PickerLocationId.$(SuggestedStartLocation);\n \n picker.ViewMode = PickerViewMode.$(ViewMode);\n\n // Show the picker dialog window\n var files = await picker.PickMultipleFilesAsync();\n\n if (files.Count \u003E 0)\n {\n PickedMultipleFilesTextBlock.Text = \u0022\u0022;\n foreach (var file in files)\n {\n PickedMultipleFilesTextBlock.Text \u002B= \u0022- Picked: \u0022 \u002B file.Path \u002B Environment.NewLine;\n }\n }\n else\n {\n PickedMultipleFilesTextBlock.Text = \u0022No files selected.\u0022;\n }\n\n //re-enable the button\n button.IsEnabled = true;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StoragePickersPickMultipleFiles.txt",
+ "source": "WinUIGallery/Samples/StoragePickers/StoragePickersPickMultipleFiles.txt",
+ "name": "Pick Multiple Files",
+ "codePlaceholdersPresent": [
+ "FileType",
+ "SuggestedStartLocation",
+ "ViewMode"
+ ]
+ }
+ },
+ {
+ "header": "Save file",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CTextBox x:Name=\u0022FileContentTextBox\u0022 Header=\u0022File content\u0022 TextWrapping=\u0022Wrap\u0022 AcceptsReturn=\u0022True\u0022\n Width=\u0022500\u0022 Height=\u0022200\u0022 Text=\u0022Hello, WinUI!\u0022 IsSpellCheckEnabled=\u0022False\u0022 /\u003E\n \u003CButton x:Name=\u0022SaveFileButton\u0022 Content=\u0022Save a file\u0022 Click=\u0022SaveFileButton_Click\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022SavedFileTextBlock\u0022 Grid.Column=\u00221\u0022 Text=\u0022No file saved\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "code": "private async void SaveFileButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n button.IsEnabled = false;\n\n var picker = new FileSavePicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId);\n$(TxtFileType)$(JsonFileType)$(XmlFileType)\n picker.DefaultFileExtension = \u0022.txt\u0022;\n\n picker.SuggestedFileName = \u0022NewDocument\u0022;\n\n picker.CommitButtonText = \u0022Save File\u0022;\n\n picker.SuggestedStartLocation = PickerLocationId.$(SuggestedStartLocation);\n \n picker.SuggestedFolder = \u0022$(SuggestedFolder)\u0022;\n\n // Show the picker dialog\n var result = await picker.PickSaveFileAsync();\n\n if (result != null)\n {\n string savePath = result.Path;\n await File.WriteAllTextAsync(savePath, FileContentTextBox.Text);\n SavedFileTextBlock.Text = \u0022File saved to: \u0022 \u002B savePath;\n }\n else\n {\n SavedFileTextBlock.Text = \u0022File save canceled.\u0022;\n }\n\n button.IsEnabled = true;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StoragePickersSaveFile.txt",
+ "source": "WinUIGallery/Samples/StoragePickers/StoragePickersSaveFile.txt",
+ "name": "Save File",
+ "codePlaceholdersPresent": [
+ "TxtFileType",
+ "JsonFileType",
+ "XmlFileType",
+ "SuggestedStartLocation",
+ "SuggestedFolder"
+ ]
+ }
+ },
+ {
+ "header": "Pick folder",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CButton x:Name=\u0022PickFolderButton\u0022 Content=\u0022Pick a folder\u0022 Click=\u0022PickFolderButton_Click\u0022 /\u003E\n \u003CTextBlock x:Name=\u0022PickedFolderTextBlock\u0022 Text=\u0022No folder picked\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "code": "private async void PickFolderButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n // disable the button to avoid double-clicking\n button.IsEnabled = false;\n\n // Clear previous returned folder name\n PickedFolderTextBlock.Text = \u0022\u0022;\n\n var picker = new FolderPicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId);\n\n picker.CommitButtonText = \u0022Pick Folder\u0022;\n picker.SuggestedStartLocation = PickerLocationId.$(SuggestedStartLocation);\n picker.ViewMode = PickerViewMode.$(ViewMode);\n\n // Show the picker dialog window\n var folder = await picker.PickSingleFolderAsync();\n PickedFolderTextBlock.Text = folder != null\n ? \u0022Picked: \u0022 \u002B folder.Path\n : \u0022No folder selected.\u0022;\n\n // re-enable the button\n button.IsEnabled = true;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StoragePickersPickFolder.txt",
+ "source": "WinUIGallery/Samples/StoragePickers/StoragePickersPickFolder.txt",
+ "name": "Pick Folder",
+ "codePlaceholdersPresent": [
+ "SuggestedStartLocation",
+ "ViewMode"
+ ]
+ }
+ },
+ {
+ "header": "Pick a file and display its thumbnail",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022 Orientation=\u0022Horizontal\u0022\u003E\n \u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CButton x:Name=\u0022PickFileForThumbnailButton\u0022 Content=\u0022Pick a file\u0022 Click=\u0022PickFileForThumbnailButton_Click\u0022/\u003E\n \u003CTextBlock x:Name=\u0022ThumbnailDetailsTextBlock\u0022 Text=\u0022No file picked\u0022 TextWrapping=\u0022Wrap\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003CBorder Width=\u0022160\u0022 Height=\u0022160\u0022 Background=\u0022{ThemeResource SubtleFillColorTertiaryBrush}\u0022\n CornerRadius=\u00224\u0022 HorizontalAlignment=\u0022Left\u0022\u003E\n \u003CImage x:Name=\u0022ThumbnailImage\u0022 Stretch=\u0022Uniform\u0022 AutomationProperties.Name=\u0022File thumbnail\u0022/\u003E\n \u003C/Border\u003E\n\u003C/StackPanel\u003E",
+ "code": "private async void PickFileForThumbnailButton_Click(object sender, RoutedEventArgs e)\n{\n if (sender is Button button)\n {\n button.IsEnabled = false;\n\n // 1) Pick a file using the new WinAppSDK Microsoft.Windows.Storage.Pickers API.\n var picker = new FileOpenPicker(button.XamlRoot.ContentIslandEnvironment.AppWindowId);\n picker.FileTypeFilter.Add(\u0022*\u0022);\n\n var pickResult = await picker.PickSingleFileAsync();\n if (pickResult == null)\n {\n ThumbnailDetailsTextBlock.Text = \u0022No file selected.\u0022;\n ThumbnailImage.Source = null;\n button.IsEnabled = true;\n\n return;\n }\n\n // 2) The new picker returns a path string; bridge to a StorageFile to access\n // thumbnail APIs (Windows.Storage.FileProperties has no WinAppSDK replacement).\n var file = await Windows.Storage.StorageFile.GetFileFromPathAsync(pickResult.Path);\n\n var thumbnailMode = (Windows.Storage.FileProperties.ThumbnailMode)ThumbnailModeComboBox.SelectedItem;\n\n // NumberBox.Value is NaN when the user clears the field; fall back to a sane default.\n double rawSize = ThumbnailSizeNumberBox.Value;\n uint size = double.IsNaN(rawSize) || rawSize \u003C= 0 ? 200u : (uint)rawSize;\n\n // 3) Request the thumbnail. ThumbnailMode hints how the system should render it\n // (e.g. PicturesView for photos, MusicView for album art, DocumentsView for icons).\n // Some modes throw for incompatible file types (e.g. PicturesView on a .txt file),\n // so wrap the call and report the failure to the user.\n try\n {\n using var thumbnail = await file.GetThumbnailAsync(\n thumbnailMode, size, Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale);\n if (thumbnail != null)\n {\n var bitmap = new Microsoft.UI.Xaml.Media.Imaging.BitmapImage();\n await bitmap.SetSourceAsync(thumbnail);\n ThumbnailImage.Source = bitmap;\n\n ThumbnailDetailsTextBlock.Text =\n $\u0022File: {file.Name}\\n\u0022 \u002B\n $\u0022Mode: ThumbnailMode.{thumbnailMode}\\n\u0022 \u002B\n $\u0022Requested size: {size}\\n\u0022 \u002B\n $\u0022Returned size: {thumbnail.OriginalWidth} x {thumbnail.OriginalHeight}\u0022;\n }\n else\n {\n ThumbnailImage.Source = null;\n ThumbnailDetailsTextBlock.Text = \u0022No thumbnail available for the selected file.\u0022;\n }\n }\n catch (Exception ex)\n {\n ThumbnailImage.Source = null;\n ThumbnailDetailsTextBlock.Text =\n $\u0022Could not retrieve a thumbnail for \\\u0022{file.Name}\\\u0022 using ThumbnailMode.{thumbnailMode}.\\n\u0022 \u002B\n $\u0022Try a different mode (for example, SingleItem) or a different file.\\n\u0022 \u002B\n $\u0022({ex.HResult:X8})\u0022;\n }\n\n button.IsEnabled = true;\n\n UIHelper.AnnounceActionForAccessibility(button, ThumbnailDetailsTextBlock.Text, \u0022ThumbnailPickedNotificationId\u0022);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "StoragePickersFileThumbnail.txt",
+ "source": "WinUIGallery/Samples/StoragePickers/StoragePickersFileThumbnail.txt",
+ "name": "File Thumbnail"
+ }
+ }
+ ]
+ },
+ {
+ "id": "swipecontrol",
+ "name": "SwipeControl",
+ "description": "Touch gesture for quick menu actions on items.",
+ "details": "Touch gesture for quick menu actions on items.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "GridView",
+ "ListView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "SwipeItem",
+ "gesture"
+ ],
+ "docs": [
+ {
+ "title": "SwipeControl - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.swipecontrol"
+ },
+ {
+ "title": "SwipeItems - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.swipeitems"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/swipe"
+ },
+ {
+ "title": "Gesture Actions",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/collection-commanding"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SwipeControl",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/SwipeControl/SwipeControlPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SwipeControl/SwipeControlPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ListView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Swipe right to reveal actions",
+ "xaml": "\u003CBorder\u003E\n \u003CBorder.Resources\u003E\n \u003CFontIconSource x:Key=\u0022AcceptIcon\u0022 Glyph=\u0022\u0026#xE8FB;\u0022/\u003E\n \u003CFontIconSource x:Key=\u0022FlagIcon\u0022 Glyph=\u0022\u0026#xE7C1;\u0022/\u003E\n\n \u003CSwipeItems x:Key=\u0022left\u0022 Mode=\u0022Reveal\u0022\u003E\n \u003CSwipeItem Text=\u0022Accept\u0022 IconSource=\u0022{StaticResource AcceptIcon}\u0022 Invoked=\u0022Accept_ItemInvoked\u0022/\u003E\n \u003CSwipeItem Text=\u0022Flag\u0022 IconSource=\u0022{StaticResource FlagIcon}\u0022 Invoked=\u0022Flag_ItemInvoked\u0022/\u003E\n \u003C/SwipeItems\u003E\n \u003C/Border.Resources\u003E\n \u003CSwipeControl BorderThickness=\u00221\u0022\n LeftItems=\u0022{StaticResource left}\u0022 BorderBrush=\u0022{ThemeResource ButtonBackground}\u0022\n Width=\u0022300\u0022 Margin=\u002212\u0022 Height=\u002268\u0022\u003E\n \u003CTextBlock Text=\u0022Swipe Right\u0022 Margin=\u002212\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/SwipeControl\u003E\n\u003C/Border\u003E",
+ "gallery": {
+ "snippet": "SwipeControlSwipeRightRevealActions.txt",
+ "source": "WinUIGallery/Samples/SwipeControl/SwipeControlSwipeRightRevealActions.txt",
+ "name": "Swipe Right Reveal Actions"
+ }
+ },
+ {
+ "header": "Swipe left to invoke an execute",
+ "xaml": "\u003CBorder\u003E\n \u003CBorder.Resources\u003E\n \u003CFontIconSource x:Key=\u0022DeleteIcon\u0022 Glyph=\u0022\u0026#xE74D;\u0022/\u003E\n \u003CSwipeItems x:Key=\u0022right\u0022 Mode=\u0022Execute\u0022\u003E\n \u003CSwipeItem Text=\u0022Archive\u0022 IconSource=\u0022{StaticResource ArchiveIcon}\u0022\n BehaviorOnInvoked=\u0022Close\u0022 Invoked=\u0022DeleteOne_ItemInvoked\u0022/\u003E\n \u003C/SwipeItems\u003E\n \u003C/Border.Resources\u003E\n \u003CSwipeControl BorderThickness=\u00221\u0022 BorderBrush=\u0022{ThemeResource ButtonBackground}\u0022\n RightItems=\u0022{StaticResource right}\u0022\n Width=\u0022300\u0022 Margin=\u002212\u0022 Height=\u002268\u0022\u003E\n \u003CTextBlock Text=\u0022Swipe Left\u0022 Margin=\u002212\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/SwipeControl\u003E\n\u003C/Border\u003E",
+ "gallery": {
+ "snippet": "SwipeControlSwipeLeftInvokeExecute.txt",
+ "source": "WinUIGallery/Samples/SwipeControl/SwipeControlSwipeLeftInvokeExecute.txt",
+ "name": "Swipe Left Invoke Execute"
+ }
+ },
+ {
+ "header": "Custom Swipe in a ListView",
+ "xaml": "\u003CListView x:Name=\u0022lv\u0022 Width=\u0022400\u0022 Height=\u0022300\u0022 Margin=\u002212\u0022\u003E\n \u003CListView.Resources\u003E\n \u003CFontIconSource x:Key=\u0022ReplyAllIcon\u0022 Glyph=\u0022\u0026#xE8C2;\u0022/\u003E\n \u003CFontIconSource x:Key=\u0022ReadIcon\u0022 Glyph=\u0022\u0026#xE8C3;\u0022/\u003E\n \u003CFontIconSource x:Key=\u0022DeleteIcon\u0022 Glyph=\u0022\u0026#xE74D;\u0022/\u003E\n\n \u003CSwipeItems x:Key=\u0022left\u0022 Mode=\u0022Reveal\u0022\u003E\n \u003CSwipeItem Text=\u0022Reply All\u0022 IconSource=\u0022{StaticResource ReplyAllIcon}\u0022\n Background=\u0022#FF3e6fa7\u0022 Foreground=\u0022White\u0022/\u003E\n \u003CSwipeItem Text=\u0022Open\u0022 IconSource=\u0022{StaticResource ReadIcon}\u0022\n Background=\u0022#FFff9501\u0022 Foreground=\u0022White\u0022/\u003E\n \u003C/SwipeItems\u003E\n \u003CSwipeItems x:Key=\u0022right\u0022 Mode=\u0022Execute\u0022\u003E\n \u003CSwipeItem Text=\u0022Delete\u0022 IconSource=\u0022{StaticResource DeleteIcon}\u0022\n Background=\u0022#FFF4B183\u0022 Invoked=\u0022DeleteItem_ItemInvoked\u0022/\u003E\n \u003C/SwipeItems\u003E\n \u003C/ListView.Resources\u003E\n\n \u003CListView.ItemTemplate\u003E\n \u003CDataTemplate\u003E\n \u003CSwipeControl BorderThickness=\u00220,1,0,0\u0022 BorderBrush=\u0022{ThemeResource ButtonBackground}\u0022 Height=\u002268\u0022\n Width=\u0022800\u0022 MinWidth=\u0022200\u0022 LeftItems=\u0022{StaticResource left}\u0022\n RightItems=\u0022{StaticResource right}\u0022\u003E\n \u003CTextBlock Text=\u0022{Binding}\u0022 FontSize=\u002224\u0022 Margin=\u002212\u0022\n HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/SwipeControl\u003E\n \u003C/DataTemplate\u003E\n \u003C/ListView.ItemTemplate\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "SwipeControlCustomSwipeListview.txt",
+ "source": "WinUIGallery/Samples/SwipeControl/SwipeControlCustomSwipeListview.txt",
+ "name": "Custom Swipe Listview"
+ }
+ },
+ {
+ "header": "Gradient Background",
+ "xaml": "\u003CBorder\u003E\n \u003CBorder.Resources\u003E\n \u003CFontIconSource x:Key=\u0022LockIcon\u0022 Glyph=\u0022\u0026#xE72E;\u0022/\u003E\n \u003CLinearGradientBrush x:Key=\u0022PurpleGradient\u0022 StartPoint=\u00220,0.5\u0022 EndPoint=\u00221,0.5\u0022\u003E\n \u003CGradientStop Color=\u0022#ff8990f9\u0022 Offset=\u00220.0\u0022/\u003E\n \u003CGradientStop Color=\u0022#ff5b66fb\u0022 Offset=\u00220.5\u0022/\u003E\n \u003CGradientStop Color=\u0022#ff5c1df4\u0022 Offset=\u00221.0\u0022/\u003E\n \u003C/LinearGradientBrush\u003E\n \u003CSwipeItems x:Key=\u0022right\u0022 Mode=\u0022Execute\u0022\u003E\n \u003CSwipeItem Text=\u0022Lock\u0022 Background=\u0022{StaticResource PurpleGradient}\u0022 \n BehaviorOnInvoked=\u0022Close\u0022 IconSource=\u0022{StaticResource LockIcon}\u0022/\u003E\n \u003C/SwipeItems\u003E\n \u003C/Border.Resources\u003E\n \u003CSwipeControl BorderThickness=\u00221\u0022 BorderBrush=\u0022{ThemeResource ButtonBackground}\u0022\n RightItems=\u0022{StaticResource right}\u0022\n Width=\u0022500\u0022 Margin=\u002212\u0022 Height=\u002268\u0022\u003E\n \u003CTextBlock Text=\u0022Swipe Left\u0022 Margin=\u002212\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/SwipeControl\u003E\n\u003C/Border\u003E",
+ "gallery": {
+ "snippet": "SwipeControlGradientBackground.txt",
+ "source": "WinUIGallery/Samples/SwipeControl/SwipeControlGradientBackground.txt",
+ "name": "Gradient Background"
+ }
+ },
+ {
+ "header": "Custom icons",
+ "xaml": "\u003CBorder\u003E\n \u003CBorder.Resources\u003E\n \u003CSwipeItems x:Key=\u0022left\u0022 Mode=\u0022Reveal\u0022\u003E\n \u003CSwipeItem Text=\u0022Coffee\u0022\u003E\n \u003CSwipeItem.IconSource\u003E\n \u003CBitmapIconSource UriSource=\u0022ms-appx:///Assets/SampleMedia/CoffeeCup.png\u0022/\u003E\n \u003C/SwipeItem.IconSource\u003E\n \u003C/SwipeItem\u003E\n \u003C/SwipeItems\u003E\n \u003C/Border.Resources\u003E\n \u003CSwipeControl BorderThickness=\u00221\u0022\n LeftItems=\u0022{StaticResource left}\u0022 BorderBrush=\u0022{ThemeResource ButtonBackground}\u0022\n Width=\u0022300\u0022 Margin=\u002212\u0022 Height=\u002268\u0022\u003E\n \u003CTextBlock Text=\u0022Swipe Right\u0022 Margin=\u002212\u0022\n HorizontalAlignment=\u0022Center\u0022 VerticalAlignment=\u0022Center\u0022/\u003E\n \u003C/SwipeControl\u003E\n\u003C/Border\u003E",
+ "gallery": {
+ "snippet": "SwipeControlCustomIcons.txt",
+ "source": "WinUIGallery/Samples/SwipeControl/SwipeControlCustomIcons.txt",
+ "name": "Custom Icons"
+ }
+ }
+ ]
+ },
+ {
+ "id": "systembackdropelement",
+ "name": "SystemBackdropElement",
+ "description": "An element to host system backdrop materials.",
+ "details": "SystemBackdropElement applies system backdrop materials (Mica and Acrylic) to specific areas inside the UI tree, extending these materials beyond the window background to enable more flexible and immersive designs.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "Mica",
+ "Acrylic",
+ "material"
+ ],
+ "docs": [
+ {
+ "title": "SystemBackdropElement - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.systembackdropelement"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SystemBackdropElement",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/SystemBackdropElement/SystemBackdropElementPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SystemBackdropElement/SystemBackdropElementPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "badges": [
+ "New"
+ ]
+ },
+ "samples": []
+ },
+ {
+ "id": "systembackdrops",
+ "name": "System Backdrops (Mica/Acrylic)",
+ "description": "System backdrops, like Mica and Acrylic, for app windows.",
+ "details": "System backdrops apply a material effect to the window background. Mica is opaque and samples the desktop wallpaper; Desktop Acrylic is semi-transparent and shows a blurred view of what is behind the window. Available backdrop kinds: Mica, Mica Alt, Desktop Acrylic Base, and Desktop Acrylic Thin. Use the built-in MicaBackdrop or DesktopAcrylicBackdrop types for simplicity, or use MicaController / DesktopAcrylicController for full customization.",
+ "apiNamespace": "Microsoft.UI.Composition.SystemBackdrops",
+ "relatedControls": [
+ "AcrylicBrush"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject"
+ ],
+ "curatedKeywords": [
+ "Mica",
+ "Acrylic",
+ "window material"
+ ],
+ "docs": [
+ {
+ "title": "SystemBackdrop - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.systembackdrop"
+ },
+ {
+ "title": "MicaBackdrop - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.micabackdrop"
+ },
+ {
+ "title": "DesktopAcrylicBackdrop - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.desktopacrylicbackdrop"
+ },
+ {
+ "title": "MicaController - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.composition.systembackdrops.micacontroller"
+ },
+ {
+ "title": "DesktopAcrylicController - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.composition.systembackdrops.desktopacryliccontroller"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "SystemBackdrops",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/SystemBackdrops/SystemBackdropsPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/SystemBackdrops/SystemBackdropsPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Acrylic"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Backdrop types",
+ "xaml": "\u003C!-- Mica --\u003E\n\u003CWindow.SystemBackdrop\u003E\n \u003CMicaBackdrop/\u003E\n\u003C/Window.SystemBackdrop\u003E\n \n\u003C!-- Mica Alt --\u003E\n\u003CWindow.SystemBackdrop\u003E\n \u003CMicaBackdrop Kind=\u0022BaseAlt\u0022/\u003E\n\u003C/Window.SystemBackdrop\u003E\n\n\u003C!-- Acrylic --\u003E\n\u003CWindow.SystemBackdrop\u003E\n \u003CDesktopAcrylicBackdrop/\u003E\n\u003C/Window.SystemBackdrop\u003E",
+ "code": "bool TrySetMicaBackdrop(bool useMicaAlt)\n{\n if (SystemBackdrops.MicaController.IsSupported())\n {\n MicaBackdrop micaBackdrop = new MicaBackdrop();\n micaBackdrop.Kind = useMicaAlt ? MicaKind.BaseAlt : MicaKind.Base;\n SystemBackdrop = micaBackdrop;\n\n return true; // Succeeded.\n }\n\n return false; // Mica is not supported on this system.\n}\n\nbool TrySetDesktopAcrylicBackdrop()\n{\n if (DesktopAcrylicController.IsSupported())\n {\n DesktopAcrylicBackdrop DesktopAcrylicBackdrop = new DesktopAcrylicBackdrop();\n SystemBackdrop = DesktopAcrylicBackdrop;\n\n return true; // Succeeded.\n }\n\n return false; // DesktopAcrylic is not supported on this system.\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SystemBackdropsBackdropTypes.txt",
+ "source": "WinUIGallery/Samples/SystemBackdrops/SystemBackdropsBackdropTypes.txt",
+ "name": "Backdrop Types"
+ }
+ },
+ {
+ "header": "MicaController",
+ "code": "using System.Runtime.InteropServices;\nusing WinRT;\nusing Microsoft.UI.Composition;\nusing Microsoft.UI.Composition.SystemBackdrops;\n\nMicaController micaController;\nSystemBackdropConfiguration configurationSource;\n\nbool TrySetMicaBackdrop(bool useMicaAlt)\n{\n if (MicaController.IsSupported())\n {\n DispatcherQueue.EnsureSystemDispatcherQueue();\n\n // Hooking up the policy object\n configurationSource = new SystemBackdropConfiguration();\n Activated \u002B= Window_Activated;\n Closed \u002B= Window_Closed;\n ((FrameworkElement)Content).ActualThemeChanged \u002B= Window_ThemeChanged;\n\n // Initial configuration state.\n configurationSource.IsInputActive = true;\n SetConfigurationSourceTheme();\n\n micaController = new MicaController();\n micaController.Kind = useMicaAlt ? MicaKind.BaseAlt : MicaKind.Base;\n\n // Enable the system backdrop.\n micaController.AddSystemBackdropTarget(this.As\u003CICompositionSupportsSystemBackdrop\u003E());\n micaController.SetSystemBackdropConfiguration(configurationSource);\n return true; // Succeeded.\n }\n\n return false; // Mica is not supported on this system.\n}\n\nprivate void Window_Activated(object sender, WindowActivatedEventArgs args)\n{\n configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;\n}\n\nprivate void Window_Closed(object sender, WindowEventArgs args)\n{\n // Make sure any Mica/Acrylic controller is disposed\n if (micaController != null)\n {\n micaController.Dispose();\n micaController = null;\n }\n this.Activated -= Window_Activated;\n configurationSource = null;\n}\n\nprivate void Window_ThemeChanged(FrameworkElement sender, object args)\n{\n if (configurationSource != null)\n {\n SetConfigurationSourceTheme();\n }\n}\n\nprivate void SetConfigurationSourceTheme()\n{\n switch (((FrameworkElement)Content).ActualTheme)\n {\n case ElementTheme.Dark: configurationSource.Theme = SystemBackdropTheme.Dark; break;\n case ElementTheme.Light: configurationSource.Theme = SystemBackdropTheme.Light; break;\n case ElementTheme.Default: configurationSource.Theme = SystemBackdropTheme.Default; break;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SystemBackdropsMicacontroller.txt",
+ "source": "WinUIGallery/Samples/SystemBackdrops/SystemBackdropsMicacontroller.txt",
+ "name": "Micacontroller"
+ }
+ },
+ {
+ "header": "DesktopAcrylicController",
+ "code": "using System.Runtime.InteropServices;\nusing WinRT;\nusing Microsoft.UI.Composition;\nusing Microsoft.UI.Composition.SystemBackdrops;\n\nSystemBackdrops.DesktopAcrylicController acrylicController;\nSystemBackdrops.SystemBackdropConfiguration configurationSource;\n\nbool TrySetAcrylicBackdrop(bool useAcrylicThin)\n{\n if (DesktopAcrylicController.IsSupported())\n {\n DispatcherQueue.EnsureSystemDispatcherQueue();\n\n // Hooking up the policy object\n configurationSource = new SystemBackdropConfiguration();\n Activated \u002B= Window_Activated;\n Closed \u002B= Window_Closed;\n ((FrameworkElement)Content).ActualThemeChanged \u002B= Window_ThemeChanged;\n\n // Initial configuration state.\n configurationSource.IsInputActive = true;\n SetConfigurationSourceTheme();\n\n acrylicController = new DesktopAcrylicController();\n acrylicController.Kind = useAcrylicThin ? DesktopAcrylicKind.Thin : DesktopAcrylicKind.Base;\n\n // Enable the system backdrop.\n acrylicController.AddSystemBackdropTarget(As\u003CICompositionSupportsSystemBackdrop\u003E());\n acrylicController.SetSystemBackdropConfiguration(configurationSource);\n return true; // Succeeded.\n }\n\n return false; // Acrylic is not supported on this system.\n}\n\nprivate void Window_Activated(object sender, WindowActivatedEventArgs args)\n{\n configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated;\n}\n\nprivate void Window_Closed(object sender, WindowEventArgs args)\n{\n // Make sure any Mica/Acrylic controller is disposed\n if (acrylicController != null)\n {\n acrylicController.Dispose();\n acrylicController = null;\n }\n Activated -= Window_Activated;\n configurationSource = null;\n}\n\nprivate void Window_ThemeChanged(FrameworkElement sender, object args)\n{\n if (configurationSource != null)\n {\n SetConfigurationSourceTheme();\n }\n}\n\nprivate void SetConfigurationSourceTheme()\n{\n switch (((FrameworkElement)this.Content).ActualTheme)\n {\n case ElementTheme.Dark: configurationSource.Theme = SystemBackdropTheme.Dark; break;\n case ElementTheme.Light: configurationSource.Theme = SystemBackdropTheme.Light; break;\n case ElementTheme.Default: configurationSource.Theme = SystemBackdropTheme.Default; break;\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SystemBackdropsDesktopacryliccontroller.txt",
+ "source": "WinUIGallery/Samples/SystemBackdrops/SystemBackdropsDesktopacryliccontroller.txt",
+ "name": "Desktopacryliccontroller"
+ }
+ }
+ ]
+ },
+ {
+ "id": "tabview",
+ "name": "TabView",
+ "description": "A control that displays a collection of tabs that can be used to display several documents.",
+ "details": "TabView provides the user with a collection of tabs that can be used to display several documents.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Pivot",
+ "NavigationView",
+ "ListView"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Input",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "tabs",
+ "tabbed",
+ "tab control"
+ ],
+ "docs": [
+ {
+ "title": "TabView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.tabview"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/tab-view"
+ },
+ {
+ "title": "Show multiple views for an app",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/show-multiple-views"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TabView",
+ "group": {
+ "id": "Navigation",
+ "title": "Navigation"
+ },
+ "page": "WinUIGallery/Samples/TabView/TabViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TabView/TabViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "badges": [
+ "Updated"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ListView",
+ "microsoft/WinUI-Gallery#NavigationView",
+ "microsoft/WinUI-Gallery#Pivot"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A TabView with support for adding, closing, and rearranging tabs",
+ "xaml": "\u003CTabView AddTabButtonClick=\u0022TabView_AddButtonClick\u0022 TabCloseRequested=\u0022TabView_TabCloseRequested\u0022 Loaded=\u0022TabView_Loaded\u0022 /\u003E",
+ "code": "private void TabView_Loaded(object sender, RoutedEventArgs e)\n{\n for (int i = 0; i \u003C 3; i\u002B\u002B)\n {\n (sender as TabView)?.TabItems.Add(CreateNewTab(i));\n }\n}\n\nprivate void TabView_AddButtonClick(TabView sender, object args)\n{\n sender.TabItems.Add(CreateNewTab(sender.TabItems.Count));\n}\n\nprivate void TabView_TabCloseRequested(TabView sender, TabViewTabCloseRequestedEventArgs args)\n{\n sender.TabItems.Remove(args.Tab);\n}\n\nprivate TabViewItem CreateNewTab(int index)\n{\n TabViewItem newItem = new TabViewItem();\n\n newItem.Header = $\u0022Document {index}\u0022;\n newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Document };\n\n // The content of the tab is often a frame that contains a page, though it could be any UIElement.\n Frame frame = new Frame();\n\n switch (index % 3)\n {\n case 0:\n frame.Navigate(typeof(SamplePage1));\n break;\n case 1:\n frame.Navigate(typeof(SamplePage2));\n break;\n case 2:\n frame.Navigate(typeof(SamplePage3));\n break;\n }\n\n newItem.Content = frame;\n\n return newItem;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TabviewSupportAddingClosing.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewSupportAddingClosing.txt",
+ "name": "Support Adding Closing"
+ }
+ },
+ {
+ "header": "A TabView with TabViewItems defined in markup",
+ "xaml": "\u003CTabView AddTabButtonClick=\u0022TabView_AddButtonClick\u0022 TabCloseRequested=\u0022TabView_TabCloseRequested\u0022\u003E\n \u003CTabView.TabItems\u003E\n \u003CTabViewItem Header=\u0022Document 0\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Placeholder\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003Csamplepages:SamplePage1 /\u003E\n \u003C/TabViewItem\u003E\n \u003CTabViewItem Header=\u0022Document 1\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Placeholder\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003Csamplepages:SamplePage2 /\u003E\n \u003C/TabViewItem\u003E\n \u003CTabViewItem Header=\u0022Document 2\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Placeholder\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003Csamplepages:SamplePage3 /\u003E\n \u003C/TabViewItem\u003E\n \u003C/TabView.TabItems\u003E\n\u003C/TabView\u003E",
+ "xmlnsImports": [
+ "xmlns:samplepages=\u0022using:WinUIGallery.SamplePages\u0022"
+ ],
+ "gallery": {
+ "snippet": "TabviewTabviewitemsDefinedMarkup.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewTabviewitemsDefinedMarkup.txt",
+ "name": "Tabviewitems Defined Markup"
+ }
+ },
+ {
+ "header": "A TabView bound to a collection of MyData objects",
+ "xaml": "\u003CTabView TabItemsSource=\u0022{x:Bind myDatas, Mode=OneWay}\u0022 AddTabButtonClick=\u0022TabViewItemsSourceSample_AddTabButtonClick\u0022 TabCloseRequested=\u0022TabViewItemsSourceSample_TabCloseRequested\u0022 /\u003E",
+ "gallery": {
+ "snippet": "TabviewBoundCollectionMydata.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewBoundCollectionMydata.txt",
+ "name": "Bound Collection Mydata"
+ }
+ },
+ {
+ "header": "A TabView with keyboarding support",
+ "xaml": "\u003CTabView AddTabButtonClick=\u0022TabView_AddButtonClick\u0022 TabCloseRequested=\u0022TabView_TabCloseRequested\u0022 Loaded=\u0022TabView_Loaded\u0022\u003E\n \u003CTabView.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Key=\u0022T\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NewTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022W\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022CloseSelectedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number1\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number2\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number3\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number4\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number5\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number6\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number7\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number8\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003CKeyboardAccelerator Key=\u0022Number9\u0022 Modifiers=\u0022Control\u0022 Invoked=\u0022NavigateToNumberedTabKeyboardAccelerator_Invoked\u0022 /\u003E\n \u003C/TabView.KeyboardAccelerators\u003E\n\u003C/TabView\u003E",
+ "code": "private void NewTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)\n{\n if (ars.Element is not TabView senderTabView)\n {\n return;\n }\n\n senderTabView.TabItems.Add(CreateNewTab(senderTabView.TabItems.Count));\n\n args.Handled = true;\n}\n\nprivate void CloseSelectedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)\n{\n if (args.Element is not TabView invokedTabView)\n {\n return;\n }\n\n // Only close the selected tab if it is closeable\n if ((invokedTabView.SelectedItem as TabViewItem)?.IsClosable is true)\n {\n invokedTabView.TabItems.Remove(invokedTabView.SelectedItem);\n }\n\n args.Handled = true;\n}\n\nprivate void NavigateToNumberedTabKeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)\n{\n if (args.Element is not TabView invokedTabView)\n {\n return;\n }\n\n int tabToSelect = 0;\n\n switch (sender.Key)\n {\n case Windows.System.VirtualKey.Number1:\n tabToSelect = 0;\n break;\n case Windows.System.VirtualKey.Number2:\n tabToSelect = 1;\n break;\n case Windows.System.VirtualKey.Number3:\n tabToSelect = 2;\n break;\n case Windows.System.VirtualKey.Number4:\n tabToSelect = 3;\n break;\n case Windows.System.VirtualKey.Number5:\n tabToSelect = 4;\n break;\n case Windows.System.VirtualKey.Number6:\n tabToSelect = 5;\n break;\n case Windows.System.VirtualKey.Number7:\n tabToSelect = 6;\n break;\n case Windows.System.VirtualKey.Number8:\n tabToSelect = 7;\n break;\n case Windows.System.VirtualKey.Number9:\n // Select the last tab\n tabToSelect = invokedTabView.TabItems.Count - 1;\n break;\n }\n\n // Only select the tab if it is in the list\n if (tabToSelect \u003C invokedTabView.TabItems.Count)\n {\n invokedTabView.SelectedIndex = tabToSelect;\n }\n\n args.Handled = true;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TabviewKeyboardingSupport.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewKeyboardingSupport.txt",
+ "name": "Keyboarding Support"
+ }
+ },
+ {
+ "header": "You can put custom content in TabStripHeader and TabStripFooter",
+ "xaml": "\u003CTabView\u003E\n \u003CTabView.TabStripHeader\u003E\n \u003CTextBlock Text=\u0022TabStripHeader Content\u0022 VerticalAlignment=\u0022Center\u0022 Margin=\u00228,6\u0022 Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022 /\u003E\n \u003C/TabView.TabStripHeader\u003E\n \u003CTabView.TabStripFooter\u003E\n \u003CTextBlock Text=\u0022TabStripFooter Content\u0022 VerticalAlignment=\u0022Center\u0022 HorizontalAlignment=\u0022Right\u0022 Margin=\u00226\u0022 Style=\u0022{ThemeResource BaseTextBlockStyle}\u0022 /\u003E\n \u003C/TabView.TabStripFooter\u003E\n\u003C/TabView\u003E",
+ "gallery": {
+ "snippet": "TabViewYouPutCustomContent.txt",
+ "source": "WinUIGallery/Samples/TabView/TabViewYouPutCustomContent.txt",
+ "name": "You Put Custom Content"
+ }
+ },
+ {
+ "header": "Tab widths can either be equally sized, sized to the content of the tab, or sized to only show the icon when unselected",
+ "xaml": "\u003CTabView TabWidthMode=\u0022SizeToContent\u0022 /\u003E",
+ "gallery": {
+ "snippet": "TabViewTabWidthsEitherBe.txt",
+ "source": "WinUIGallery/Samples/TabView/TabViewTabWidthsEitherBe.txt",
+ "name": "Tab Widths Either Be"
+ }
+ },
+ {
+ "header": "The close button can be persistent or only visible on hover",
+ "xaml": "\u003CTabView /\u003E",
+ "gallery": {
+ "snippet": "TabViewCloseButtonBePersistent.txt",
+ "source": "WinUIGallery/Samples/TabView/TabViewCloseButtonBePersistent.txt",
+ "name": "Close Button Be Persistent",
+ "xamlPlaceholdersDropped": [
+ "CloseButtonOverlayMode"
+ ]
+ }
+ },
+ {
+ "header": "TabView with color tab icons",
+ "xaml": "\u003CTabView\u003E\n \u003CTabView.TabItems\u003E\n \u003CTabViewItem Header=\u0022CMD Prompt\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CBitmapIconSource UriSource=\u0022/Assets/SampleMedia/cmd.png\u0022 ShowAsMonochrome=\u0022False\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003C/TabViewItem\u003E\n \u003CTabViewItem Header=\u0022PowerShell\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CBitmapIconSource UriSource=\u0022/Assets/SampleMedia/powershell.png\u0022 ShowAsMonochrome=\u0022False\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003C/TabViewItem\u003E\n \u003CTabViewItem Header=\u0022Windows Subsystem for Linux\u0022\u003E\n \u003CTabViewItem.IconSource\u003E\n \u003CBitmapIconSource UriSource=\u0022/Assets/SampleMedia/linux.png\u0022 ShowAsMonochrome=\u0022False\u0022 /\u003E\n \u003C/TabViewItem.IconSource\u003E\n \u003C/TabViewItem\u003E\n \u003C/TabView.TabItems\u003E\n\u003C/TabView\u003E",
+ "gallery": {
+ "snippet": "TabviewColorTabIcons.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewColorTabIcons.txt",
+ "name": "Color Tab Icons"
+ }
+ },
+ {
+ "header": "A TabView with accent colored TabStrip background",
+ "xaml": "\u003CTabView\u003E\n \u003CTabView.Resources\u003E\n \u003CResourceDictionary\u003E\n \u003CResourceDictionary.ThemeDictionaries\u003E\n \u003CResourceDictionary x:Key=\u0022Light\u0022\u003E\n \u003CSolidColorBrush x:Key=\u0022TabViewBackground\u0022 Color=\u0022{ThemeResource SystemAccentColorLight2}\u0022/\u003E\n \u003C/ResourceDictionary\u003E\n \u003CResourceDictionary x:Key=\u0022Dark\u0022\u003E\n \u003CSolidColorBrush x:Key=\u0022TabViewBackground\u0022 Color=\u0022{ThemeResource SystemAccentColorDark2}\u0022/\u003E\n \u003C/ResourceDictionary\u003E\n \u003C/ResourceDictionary.ThemeDictionaries\u003E\n \u003C/ResourceDictionary\u003E\n \u003C/TabView.Resources\u003E\n\u003C/TabView\u003E",
+ "gallery": {
+ "snippet": "TabviewAccentColoredTabstrip.txt",
+ "source": "WinUIGallery/Samples/TabView/TabviewAccentColoredTabstrip.txt",
+ "name": "Accent Colored Tabstrip"
+ }
+ },
+ {
+ "header": "Complete TabView windowing sample",
+ "xaml": "Check out the TabViewWindowingSamplePage.xaml and *.cs files to see the complete code.",
+ "gallery": {
+ "snippet": "CompleteTabviewWindowingSample.txt",
+ "source": "WinUIGallery/Samples/TabView/CompleteTabviewWindowingSample.txt",
+ "name": "Complete Tabview Windowing Sample"
+ }
+ }
+ ]
+ },
+ {
+ "id": "teachingtip",
+ "name": "TeachingTip",
+ "description": "A content-rich flyout for guiding users and enabling teaching moments.",
+ "details": "The XAML TeachingTip Control provides a way for your app to guide and inform users in your application with a non-invasive and content rich notification. TeachingTip can be used for bringing focus to a new or important feature, teaching users how to perform a task, or enhancing the user workflow by providing contextually relevant information to their task at hand.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ContentDialog",
+ "Flyout",
+ "ToolTip"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "callout",
+ "coachmark"
+ ],
+ "docs": [
+ {
+ "title": "TeachingTip - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.teachingtip"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/dialogs-and-flyouts/teaching-tip"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TeachingTip",
+ "group": {
+ "id": "DialogsAndFlyouts",
+ "title": "Dialogs \u0026 flyouts"
+ },
+ "page": "WinUIGallery/Samples/TeachingTip/TeachingTipPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TeachingTip/TeachingTipPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ContentDialog",
+ "microsoft/WinUI-Gallery#Flyout",
+ "microsoft/WinUI-Gallery#ToolTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Show a targeted TeachingTip on a button.",
+ "xaml": "\u003CButton\n x:Name=\u0022TestButton1\u0022\n Click=\u0022TestButton1Click\u0022\n Content=\u0022Show TeachingTip\u0022 /\u003E\n\u003CTeachingTip\n x:Name=\u0022TestButton1TeachingTip\u0022\n Title=\u0022This is the title\u0022\n Subtitle=\u0022And this is the subtitle\u0022\n Target=\u0022{x:Bind TestButton1}\u0022\u003E\n \u003CTeachingTip.IconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Refresh\u0022 /\u003E\n \u003C/TeachingTip.IconSource\u003E\n\u003C/TeachingTip\u003E",
+ "code": "private void TestButton1Click(object sender, RoutedEventArgs e)\n{\n TestButton1TeachingTip.IsOpen = true;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ShowTargetedTeachingtipButton.txt",
+ "source": "WinUIGallery/Samples/TeachingTip/ShowTargetedTeachingtipButton.txt",
+ "name": "Show Targeted Teachingtip Button"
+ }
+ },
+ {
+ "header": "Show a non-targeted TeachingTip with buttons.",
+ "xaml": "\u003CButton\n Click=\u0022TestButton2Click\u0022\n Content=\u0022Show TeachingTip\u0022 /\u003E\n\u003CTeachingTip\n x:Name=\u0022TestButton2TeachingTip\u0022\n Title=\u0022This is the title\u0022\n ActionButtonContent=\u0022Action button\u0022\n CloseButtonContent=\u0022Close button\u0022\n IsLightDismissEnabled=\u0022True\u0022\n PlacementMargin=\u002220\u0022\n PreferredPlacement=\u0022Auto\u0022\n Subtitle=\u0022And this is the subtitle\u0022 /\u003E",
+ "code": "private void TestButton2Click(object sender, RoutedEventArgs e)\n{\n TestButton2TeachingTip.IsOpen = true;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ShowNonTargetedTeachingtip.txt",
+ "source": "WinUIGallery/Samples/TeachingTip/ShowNonTargetedTeachingtip.txt",
+ "name": "Show Non Targeted Teachingtip"
+ }
+ },
+ {
+ "header": "Show a targeted TeachingTip with hero content on a button.",
+ "xaml": "\u003CButton\n x:Name=\u0022TestButton3\u0022\n Click=\u0022TestButton3Click\u0022\n Content=\u0022Show TeachingTip\u0022 /\u003E\n\u003CTeachingTip\n x:Name=\u0022TestButton3TeachingTip\u0022\n Title=\u0022This is the title\u0022\n PreferredPlacement=\u0022Bottom\u0022\n Subtitle=\u0022And this is the subtitle\u0022\n Target=\u0022{x:Bind TestButton3}\u0022\u003E\n \u003CTeachingTip.HeroContent\u003E\n \u003CImage\n AutomationProperties.Name=\u0022Sunset\u0022\n Source=\u0022/Assets/SampleMedia/sunset.jpg\u0022 /\u003E\n \u003C/TeachingTip.HeroContent\u003E\n \u003CTeachingTip.Content\u003E\n \u003CTextBlock\n Margin=\u00220,16,0,0\u0022\n Text=\u0022Description can go here\u0022\n TextWrapping=\u0022WrapWholeWords\u0022 /\u003E\n \u003C/TeachingTip.Content\u003E\n\u003C/TeachingTip\u003E",
+ "code": "private void TestButton3Click(object sender, RoutedEventArgs e)\n{\n TestButton3TeachingTip.IsOpen = true;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ShowTargetedTeachingtipHero.txt",
+ "source": "WinUIGallery/Samples/TeachingTip/ShowTargetedTeachingtipHero.txt",
+ "name": "Show Targeted Teachingtip Hero"
+ }
+ }
+ ]
+ },
+ {
+ "id": "templates",
+ "name": "Templates",
+ "description": "Customize controls\u0027 visuals, item layouts, and data presentation in XAML.",
+ "details": "A template defines the structure and appearance of a control. Unlike styles, which set properties, templates allow you to completely customize how a control looks by redefining its visual tree (the XAML elements that make up the control). Templates provide the flexibility to change the look of controls while maintaining their functionality.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Binding",
+ "Style",
+ "Custom \u0026 User Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "FrameworkTemplate"
+ ],
+ "curatedKeywords": [
+ "ControlTemplate",
+ "DataTemplate",
+ "ItemTemplate",
+ "DataTemplateSelector"
+ ],
+ "docs": [
+ {
+ "title": "XAML Control Templates",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/xaml-control-templates"
+ },
+ {
+ "title": "ControlTemplate - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.controltemplate"
+ },
+ {
+ "title": "DataTemplate - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.datatemplate"
+ },
+ {
+ "title": "ItemsPanelTemplate - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemspaneltemplate"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Templates",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/Templates/TemplatesPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Templates/TemplatesPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "FrameworkTemplate"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Binding",
+ "microsoft/WinUI-Gallery#CustomUserControls",
+ "microsoft/WinUI-Gallery#XamlStyles"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Customize the look of a TextBox with a ControlTemplate",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.Resources\u003E\n \u003CControlTemplate x:Key=\u0022CustomTextBoxTemplate\u0022 TargetType=\u0022TextBox\u0022\u003E\n \u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CTextBlock Text=\u0022{TemplateBinding Header}\u0022 /\u003E\n \u003CBorder\n MinWidth=\u0022200\u0022\n Background=\u0022{ThemeResource CardBackgroundFillColorDefaultBrush}\u0022\n BorderBrush=\u0022{TemplateBinding BorderBrush}\u0022\n BorderThickness=\u00222\u0022\n CornerRadius=\u00224\u0022\u003E\n \u003CStackPanel Margin=\u00224\u0022 Orientation=\u0022Horizontal\u0022 Spacing=\u00224\u0022\u003E\n \u003CSymbolIcon Symbol=\u0022Edit\u0022 /\u003E\n \u003CScrollViewer\n x:Name=\u0022ContentElement\u0022\n Padding=\u0022{TemplateBinding Padding}\u0022\n HorizontalScrollBarVisibility=\u0022{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}\u0022\n VerticalScrollBarVisibility=\u0022{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/Border\u003E\n \u003C/StackPanel\u003E\n \u003C/ControlTemplate\u003E\n \u003C/Grid.Resources\u003E\n \u003CTextBox\n Padding=\u00228\u0022\n BorderBrush=\u0022{ThemeResource AccentFillColorDefaultBrush}\u0022\n Header=\u0022Enter text here\u0022\n Template=\u0022{StaticResource CustomTextBoxTemplate}\u0022 /\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "TemplatesCustomizeLookTextboxControltemplate.txt",
+ "source": "WinUIGallery/Samples/Templates/TemplatesCustomizeLookTextboxControltemplate.txt",
+ "name": "Customize Look Textbox Controltemplate"
+ }
+ },
+ {
+ "header": "Customize a ComboBox\u0027s ItemTemplate using a DataTemplate",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.Resources\u003E\n \u003CDataTemplate x:Key=\u0022CustomComboBoxItemTemplate\u0022\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022 Spacing=\u00228\u0022\u003E\n \u003CEllipse\n Width=\u00228\u0022\n Height=\u00228\u0022\n Fill=\u0022{ThemeResource AccentFillColorDefaultBrush}\u0022 /\u003E\n \u003CTextBlock Text=\u0022{Binding}\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/DataTemplate\u003E\n \u003C/Grid.Resources\u003E\n \u003CComboBox Header=\u0022Options\u0022 ItemTemplate=\u0022{StaticResource CustomComboBoxItemTemplate}\u0022 SelectedIndex=\u00220\u0022\u003E\n \u003CComboBox.Items\u003E\n \u003Cx:String\u003EOption 1\u003C/x:String\u003E\n \u003Cx:String\u003EOption 2\u003C/x:String\u003E\n \u003Cx:String\u003EOption 3\u003C/x:String\u003E\n \u003C/ComboBox.Items\u003E\n \u003C/ComboBox\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "TemplatesCustomizeComboboxItemtemplateDatatemplate.txt",
+ "source": "WinUIGallery/Samples/Templates/TemplatesCustomizeComboboxItemtemplateDatatemplate.txt",
+ "name": "Customize Combobox Itemtemplate Datatemplate"
+ }
+ },
+ {
+ "header": "Customize an ItemsControl with an ItemsPanelTemplate",
+ "xaml": "\u003CListView\u003E\n \u003CListView.ItemsPanel\u003E\n \u003CItemsPanelTemplate\u003E\n \u003CWrapGrid Orientation=\u0022Horizontal\u0022 /\u003E\n \u003C/ItemsPanelTemplate\u003E\n \u003C/ListView.ItemsPanel\u003E\n \n \u003CListViewItem\u003EItem 01\u003C/ListViewItem\u003E\n \u003CListViewItem\u003EItem 02\u003C/ListViewItem\u003E\n \u003C!-- ... --\u003E\n \u003CListViewItem\u003EItem 20\u003C/ListViewItem\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "TemplatesCustomizeItemscontrolItemspaneltemplate.txt",
+ "source": "WinUIGallery/Samples/Templates/TemplatesCustomizeItemscontrolItemspaneltemplate.txt",
+ "name": "Customize Itemscontrol Itemspaneltemplate"
+ }
+ }
+ ]
+ },
+ {
+ "id": "textblock",
+ "name": "TextBlock",
+ "description": "A lightweight control for displaying small amounts of text.",
+ "details": "TextBlock is the primary control for displaying read-only text in your app. You typically display text by setting the Text property to a simple string. You can also display a series of strings in Run elements and give each different formatting.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NumberBox",
+ "TextBox",
+ "RichTextBlock",
+ "PasswordBox",
+ "RichEditBox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "label",
+ "display text"
+ ],
+ "docs": [
+ {
+ "title": "TextBlock - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textblock"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/text-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TextBlock",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/TextBlock/TextBlockPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TextBlock/TextBlockPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#NumberBox",
+ "microsoft/WinUI-Gallery#PasswordBox",
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#RichTextBlock",
+ "microsoft/WinUI-Gallery#TextBox"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple TextBlock.",
+ "xaml": "\u003CTextBlock Text=\u0022I am a TextBlock\u0022/\u003E",
+ "gallery": {
+ "snippet": "SimpleTextblock.txt",
+ "source": "WinUIGallery/Samples/TextBlock/SimpleTextblock.txt",
+ "name": "Simple Textblock"
+ }
+ },
+ {
+ "header": "A TextBlock with a style applied.",
+ "xaml": "\u003CPage.Resources\u003E\n \u003CStyle TargetType=\u0022TextBlock\u0022 x:Key=\u0022CustomTextBlockStyle\u0022\u003E\n \u003CSetter Property=\u0022FontFamily\u0022 Value=\u0022Comic Sans MS\u0022/\u003E\n \u003CSetter Property=\u0022FontStyle\u0022 Value=\u0022Italic\u0022/\u003E\n \u003C/Style\u003E\n\u003C/Page.Resources\u003E\n\n\u003CTextBlock Text=\u0022I am a styled TextBlock\u0022 Style=\u0022{StaticResource CustomTextBlockStyle}\u0022/\u003E",
+ "gallery": {
+ "snippet": "TextblockStyleApplied.txt",
+ "source": "WinUIGallery/Samples/TextBlock/TextblockStyleApplied.txt",
+ "name": "Style Applied"
+ }
+ },
+ {
+ "header": "A TextBlock with various properties set.",
+ "xaml": "\u003CTextBlock Text=\u0022I am super excited to be here!\u0022 FontFamily=\u0022Arial\u0022\n FontSize=\u002224\u0022 FontStyle=\u0022Italic\u0022 TextWrapping=\u0022WrapWholeWords\u0022\n CharacterSpacing=\u0022200\u0022 Foreground=\u0022CornflowerBlue\u0022 /\u003E",
+ "gallery": {
+ "snippet": "TextblockVariousProperties.txt",
+ "source": "WinUIGallery/Samples/TextBlock/TextblockVariousProperties.txt",
+ "name": "Various Properties"
+ }
+ },
+ {
+ "header": "A TextBlock with inline text elements.",
+ "xaml": "\u003CTextBlock\u003E\n \u003CRun FontFamily=\u0022Times New Roman\u0022 Foreground=\u0022DarkGray\u0022\u003EText in a TextBlock doesn\u0027t have to be a simple string.\u003C/Run\u003E\n \u003CLineBreak /\u003E\n \u003CSpan\u003E\n Text can be \u003CBold\u003Ebold\u003C/Bold\u003E, \u003CItalic\u003Eitalic\u003C/Italic\u003E, or \u003CUnderline\u003Eunderlined\u003C/Underline\u003E.\n \u003C/Span\u003E\n\u003C/TextBlock\u003E",
+ "gallery": {
+ "snippet": "TextblockInlineTextElements.txt",
+ "source": "WinUIGallery/Samples/TextBlock/TextblockInlineTextElements.txt",
+ "name": "Inline Text Elements"
+ }
+ },
+ {
+ "header": "A selectable TextBlock",
+ "xaml": "\u003CTextBlock\n Text=\u0022I am a selectable TextBlock with custom SelectionHighlightColor.\u0022\n SelectionHighlightColor=\u0022DarkOrange\u0022 /\u003E",
+ "gallery": {
+ "snippet": "SelectableTextblock.txt",
+ "source": "WinUIGallery/Samples/TextBlock/SelectableTextblock.txt",
+ "name": "Selectable Textblock",
+ "xamlPlaceholdersDropped": [
+ "IsTextSelectionEnabled"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "textbox",
+ "name": "TextBox",
+ "description": "A single-line or multi-line plain text field.",
+ "details": "Use a TextBox to let a user enter simple text input in your app. You can add a header and placeholder text to let the user know what the TextBox is for, and you can customize it in other ways.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "NumberBox",
+ "TextBlock",
+ "RichTextBlock",
+ "PasswordBox",
+ "RichEditBox",
+ "AutoSuggestBox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "text input",
+ "input field",
+ "text field"
+ ],
+ "docs": [
+ {
+ "title": "TextBox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.textbox"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/text-controls"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TextBox",
+ "group": {
+ "id": "Text",
+ "title": "Text"
+ },
+ "page": "WinUIGallery/Samples/TextBox/TextBoxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TextBox/TextBoxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AutoSuggestBox",
+ "microsoft/WinUI-Gallery#NumberBox",
+ "microsoft/WinUI-Gallery#PasswordBox",
+ "microsoft/WinUI-Gallery#RichEditBox",
+ "microsoft/WinUI-Gallery#RichTextBlock",
+ "microsoft/WinUI-Gallery#TextBlock"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple TextBox.",
+ "xaml": "\u003CTextBox AutomationProperties.Name=\u0022simple TextBox\u0022/\u003E",
+ "gallery": {
+ "snippet": "SimpleTextbox.txt",
+ "source": "WinUIGallery/Samples/TextBox/SimpleTextbox.txt",
+ "name": "Simple Textbox"
+ }
+ },
+ {
+ "header": "A TextBox with a header and placeholder text.",
+ "xaml": "\u003CTextBox Header=\u0022Enter your name:\u0022 PlaceholderText=\u0022Name\u0022 /\u003E",
+ "gallery": {
+ "snippet": "TextboxHeaderPlaceholderText.txt",
+ "source": "WinUIGallery/Samples/TextBox/TextboxHeaderPlaceholderText.txt",
+ "name": "Header Placeholder Text"
+ }
+ },
+ {
+ "header": "A read-only TextBox with various properties set.",
+ "xaml": "\u003CTextBox Text=\u0022I am super excited to be here!\u0022\n AutomationProperties.Name=\u0022customized TextBox\u0022 IsReadOnly=\u0022True\u0022\n FontFamily=\u0022Arial\u0022 FontSize=\u002224\u0022 FontStyle=\u0022Italic\u0022\n CharacterSpacing=\u0022200\u0022 Foreground=\u0022#5178BE\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ReadOnlyTextboxVarious.txt",
+ "source": "WinUIGallery/Samples/TextBox/ReadOnlyTextboxVarious.txt",
+ "name": "Read Only Textbox Various"
+ }
+ },
+ {
+ "header": "A multi-line TextBox with spell checking and custom selection highlight color.",
+ "xaml": "\u003CTextBox AutomationProperties.Name=\u0022multi-line TextBox\u0022\n TextWrapping=\u0022Wrap\u0022 AcceptsReturn=\u0022True\u0022 IsSpellCheckEnabled=\u0022True\u0022\n SelectionHighlightColor=\u0022Green\u0022 MinWidth=\u0022400\u0022 /\u003E",
+ "gallery": {
+ "snippet": "MultiLineTextboxSpell.txt",
+ "source": "WinUIGallery/Samples/TextBox/MultiLineTextboxSpell.txt",
+ "name": "Multi Line Textbox Spell"
+ }
+ }
+ ]
+ },
+ {
+ "id": "themeshadow",
+ "name": "ThemeShadow",
+ "description": "Adds a depth-aware shadow to UI elements using system lighting.",
+ "details": "Adds a realistic shadow effect to UI elements using the system\u0027s lighting and depth to enhance visual hierarchy.",
+ "apiNamespace": "Microsoft.UI.Xaml.Media",
+ "relatedControls": [
+ "AcrylicBrush"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives",
+ "System.Numerics"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "Shadow"
+ ],
+ "curatedKeywords": [
+ "depth",
+ "elevation"
+ ],
+ "docs": [
+ {
+ "title": "Z-depth and shadow design guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/depth-shadow"
+ },
+ {
+ "title": "ThemeShadow - API",
+ "uri": "https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.media.themeshadow"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ThemeShadow",
+ "group": {
+ "id": "Styles",
+ "title": "Styles"
+ },
+ "page": "WinUIGallery/Samples/ThemeShadow/ThemeShadowPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ThemeShadow/ThemeShadowPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "Shadow"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Acrylic"
+ ]
+ },
+ "samples": [
+ {
+ "header": "ThemeShadow applied to a Border",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid x:Name=\u0022ShadowCastGrid\u0022/\u003E\n \u003CBorder x:Name=\u0022ShadowRect\u0022 Translation=\u00220,0,32\u0022 Loaded=\u0022ShadowRect_Loaded\u0022 Width=\u0022200\u0022 Height=\u0022200\u0022 CornerRadius=\u0022{ThemeResource OverlayCornerRadius}\u0022 Background=\u0022{ThemeResource CardBackgroundFillColorDefaultBrush}\u0022\u003E\n \u003CBorder.Shadow\u003E\n \u003CThemeShadow x:Name=\u0022shadow\u0022/\u003E\n \u003C/Border.Shadow\u003E\n \u003C/Border\u003E \n\u003C/Grid\u003E",
+ "code": "private void ShadowRect_Loaded(object sender, RoutedEventArgs e)\n{\n shadow.Receivers.Add(ShadowCastGrid);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "ThemeshadowAppliedBorder.txt",
+ "source": "WinUIGallery/Samples/ThemeShadow/ThemeshadowAppliedBorder.txt",
+ "name": "Applied Border"
+ }
+ }
+ ]
+ },
+ {
+ "id": "themetransition",
+ "name": "Theme Transitions",
+ "description": "Theme transitions are pre-packaged, easy-to-apply animations.",
+ "details": "Theme transitions are pre-packaged, easy-to-apply animations.",
+ "apiNamespace": "Microsoft.UI.Xaml",
+ "relatedControls": [
+ "Implicit Transitions",
+ "Page Transitions"
+ ],
+ "curatedKeywords": [
+ "theme transition",
+ "entrance animation",
+ "EntranceThemeTransition"
+ ],
+ "docs": [
+ {
+ "title": "Transitions - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.uielement.transitions#Windows_UI_Xaml_UIElement_Transitions"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/xaml-animation#animations-available-in-the-library"
+ },
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ThemeTransition",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/ThemeTransition/ThemeTransitionPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ThemeTransition/ThemeTransitionPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ImplicitTransition",
+ "microsoft/WinUI-Gallery#PageTransition"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Use the EntranceThemeTransition when adding items to your page.",
+ "xaml": "\u003CStackPanel x:Name=\u0022EntranceStackPanel\u0022 Orientation=\u0022Horizontal\u0022\u003E\n \u003CStackPanel.ChildrenTransitions\u003E\n \u003CTransitionCollection\u003E\n \u003CEntranceThemeTransition IsStaggeringEnabled=\u0022True\u0022 /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/StackPanel.ChildrenTransitions\u003E\n \u003CRectangle Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u00225\u0022 Fill=\u0022LightBlue\u0022 /\u003E\n \u003CRectangle Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u00225\u0022 Fill=\u0022LightBlue\u0022 /\u003E\n \u003CRectangle Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u00225\u0022 Fill=\u0022LightBlue\u0022 /\u003E\n \u003CRectangle Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u00225\u0022 Fill=\u0022LightBlue\u0022 /\u003E\n \u003CRectangle Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u00225\u0022 Fill=\u0022LightBlue\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "EntrancethemetransitionAddingItemsYour.txt",
+ "source": "WinUIGallery/Samples/ThemeTransition/EntrancethemetransitionAddingItemsYour.txt",
+ "name": "Entrancethemetransition Adding Items Your"
+ }
+ },
+ {
+ "header": "Use the RepositionThemeTransition to react to layout changes.",
+ "xaml": "\u003CRectangle x:Name=\u0022RightRectangle\u0022 Fill=\u0022Blue\u0022 \u003E\n \u003CRectangle.Transitions\u003E\n \u003CTransitionCollection\u003E\n \u003CRepositionThemeTransition /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/Rectangle.Transitions\u003E\n\u003C/Rectangle\u003E",
+ "gallery": {
+ "snippet": "RepositionthemetransitionReactLayoutChanges.txt",
+ "source": "WinUIGallery/Samples/ThemeTransition/RepositionthemetransitionReactLayoutChanges.txt",
+ "name": "Repositionthemetransition React Layout Changes"
+ }
+ },
+ {
+ "header": "Use ContentThemeTransition to animate content refreshes.",
+ "xaml": "\u003CListView\u003E\n \u003CListView.ItemContainerTransitions\u003E\n \u003CTransitionCollection\u003E\n \u003CContentThemeTransition /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/ListView.ItemContainerTransitions\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "ContentthemetransitionAnimateContentRefreshes.txt",
+ "source": "WinUIGallery/Samples/ThemeTransition/ContentthemetransitionAnimateContentRefreshes.txt",
+ "name": "Contentthemetransition Animate Content Refreshes"
+ }
+ },
+ {
+ "header": "Use AddDeleteThemeTransition to animate adding and removing items from a collection.",
+ "xaml": "\u003CListView\u003E\n \u003CListView.ItemContainerTransitions\u003E\n \u003CTransitionCollection\u003E\n \u003CAddDeleteThemeTransition /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/ListView.ItemContainerTransitions\u003E\n\u003C/ListView\u003E",
+ "gallery": {
+ "snippet": "AdddeletethemetransitionAnimateAddingRemoving.txt",
+ "source": "WinUIGallery/Samples/ThemeTransition/AdddeletethemetransitionAnimateAddingRemoving.txt",
+ "name": "Adddeletethemetransition Animate Adding Removing"
+ }
+ },
+ {
+ "header": "Use PopupThemeTransition to animate opening and closing a popup.",
+ "xaml": "\u003CPopup x:Name=\u0022ExamplePopup\u0022\u003E\n \u003CPopup.ChildTransitions\u003E\n \u003CTransitionCollection\u003E\n \u003CPopupThemeTransition /\u003E\n \u003C/TransitionCollection\u003E\n \u003C/Popup.ChildTransitions\u003E\n \u003CBorder Background=\u0022{ThemeResource FlyoutBackgroundThemeBrush}\u0022 BorderThickness=\u00222\u0022 BorderBrush=\u0022{ThemeResource SystemControlForegroundChromeGrayBrush}\u0022\u003E\n \u003CStackPanel Margin=\u002210\u0022\u003E\n \u003CTextBlock Text=\u0022This is a popup using PopupThemeTransition\u0022 /\u003E\n \u003CButton Content=\u0022Close Popup\u0022 Click=\u0022ClosePopupButton_Click\u0022 /\u003E\n \u003C/StackPanel\u003E\n \u003C/Border\u003E\n\u003C/Popup\u003E",
+ "gallery": {
+ "snippet": "PopupthemetransitionAnimateOpeningClosing.txt",
+ "source": "WinUIGallery/Samples/ThemeTransition/PopupthemetransitionAnimateOpeningClosing.txt",
+ "name": "Popupthemetransition Animate Opening Closing"
+ }
+ }
+ ]
+ },
+ {
+ "id": "timepicker",
+ "name": "TimePicker",
+ "description": "A configurable control that lets a user pick a time value.",
+ "details": "Use a TimePicker to let users set a time in your app, for example to set a reminder. The TimePicker displays three controls for hour, minute, and AM/PM. These controls are easy to use with touch or mouse, and they can be styled and configured in several different ways.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "DatePicker",
+ "CalendarView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "clock",
+ "time selection"
+ ],
+ "docs": [
+ {
+ "title": "TimePicker - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.timepicker"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/time-picker"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TimePicker",
+ "group": {
+ "id": "DateAndTime",
+ "title": "Date \u0026 time"
+ },
+ "page": "WinUIGallery/Samples/TimePicker/TimePickerPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TimePicker/TimePickerPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#CalendarView",
+ "microsoft/WinUI-Gallery#DatePicker"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple TimePicker that uses the clock format for the user\u0027s region.",
+ "xaml": "\u003CTimePicker/\u003E",
+ "gallery": {
+ "snippet": "SimpleTimepicker.txt",
+ "source": "WinUIGallery/Samples/TimePicker/SimpleTimepicker.txt",
+ "name": "Simple Timepicker"
+ }
+ },
+ {
+ "header": "A TimePicker with a header and minute increments specified.",
+ "xaml": "\u003CTimePicker Header=\u0022Arrival time\u0022 MinuteIncrement=\u002215\u0022 /\u003E",
+ "gallery": {
+ "snippet": "TimepickerHeaderMinuteIncrements.txt",
+ "source": "WinUIGallery/Samples/TimePicker/TimepickerHeaderMinuteIncrements.txt",
+ "name": "Header Minute Increments"
+ }
+ },
+ {
+ "header": "Use ClockIdentifier to override the regional clock format.",
+ "xaml": "\u003CStackPanel xmlns:sys=\u0022using:System\u0022 Spacing=\u00228\u0022\u003E\n \u003CTimePicker ClockIdentifier=\u002212HourClock\u0022 Header=\u002212-hour clock\u0022 SelectedTime=\u0022{x:Bind sys:DateTime.Now.TimeOfDay}\u0022 /\u003E\n \u003CTimePicker ClockIdentifier=\u002224HourClock\u0022 Header=\u002224-hour clock\u0022 SelectedTime=\u0022{x:Bind sys:DateTime.Now.TimeOfDay}\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "TimepickerClockIdentifiers.txt",
+ "source": "WinUIGallery/Samples/TimePicker/TimepickerClockIdentifiers.txt",
+ "name": "Clock Identifiers"
+ }
+ }
+ ]
+ },
+ {
+ "id": "titlebar",
+ "name": "TitleBar",
+ "description": "An example showing how to use the default TitleBar control.",
+ "details": "The TitleBar control provides a simple way to create a modern titlebar UX with interactive content.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "AppWindow",
+ "AppWindowTitleBar"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "title bar",
+ "caption bar",
+ "custom title bar"
+ ],
+ "docs": [
+ {
+ "title": "Title bar customization",
+ "uri": "https://learn.microsoft.com/windows/apps/develop/title-bar"
+ },
+ {
+ "title": "Title bar - design guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/basics/titlebar-design"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TitleBar",
+ "group": {
+ "id": "MultipleWindows",
+ "title": "Windowing"
+ },
+ "page": "WinUIGallery/Samples/TitleBar/TitleBarPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TitleBar/TitleBarPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "badges": [
+ "Updated"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppWindow",
+ "microsoft/WinUI-Gallery#AppWindowTitleBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "TitleBar configuration",
+ "xaml": "\u003CTitleBar\n Title=\u0022WinUI Gallery\u0022\n Subtitle=\u0022Preview\u0022\n IsBackButtonVisible=\u0022False\u0022\n IsPaneToggleButtonVisible=\u0022False\u0022\u003E\n \u003CTitleBar.Resources\u003E\n \u003C!-- TitleBar.Content uses Center alignment by default. Override to\n Stretch so the AutoSuggestBox grows with the title bar. --\u003E\n \u003CHorizontalAlignment x:Key=\u0022TitleBarContentHorizontalAlignment\u0022\u003EStretch\u003C/HorizontalAlignment\u003E\n \u003C/TitleBar.Resources\u003E\n \u003CTitleBar.IconSource\u003E\n \u003CImageIconSource ImageSource=\u0022/Assets/Tiles/GalleryIcon.ico\u0022 /\u003E\n \u003C/TitleBar.IconSource\u003E\n \u003CTitleBar.Content\u003E\n \u003CAutoSuggestBox\n MaxWidth=\u0022580\u0022\n HorizontalAlignment=\u0022Stretch\u0022\n VerticalAlignment=\u0022Center\u0022\n PlaceholderText=\u0022Search...\u0022\n QueryIcon=\u0022Find\u0022 /\u003E\n \u003C/TitleBar.Content\u003E\n \u003CTitleBar.RightHeader\u003E\n \u003CPersonPicture\n Width=\u002230\u0022\n Height=\u002230\u0022\n Initials=\u0022JD\u0022 /\u003E\n \u003C/TitleBar.RightHeader\u003E\n\u003C/TitleBar\u003E",
+ "gallery": {
+ "snippet": "TitlebarConfiguration.txt",
+ "source": "WinUIGallery/Samples/TitleBar/TitlebarConfiguration.txt",
+ "name": "Configuration"
+ }
+ },
+ {
+ "header": "TitleBar drag regions",
+ "xaml": "\u003C!-- Starting with WindowsAppSDK 2.1, TitleBar walks TitleBar.Content,\n auto-excludes interactive controls from the drag region, and lets\n non-interactive visuals (and empty space) remain draggable.\n\n Use TitleBar.IsDragRegion to override the framework decision:\n True -\u003E always draggable\n False -\u003E always clickable\n unset -\u003E framework decides (default) --\u003E\n\u003CTitleBar x:Name=\u0022titleBar\u0022 Title=\u0022Drag regions\u0022\u003E\n \u003CTitleBar.Resources\u003E\n \u003C!-- TitleBar.Content uses Center alignment by default, so a child\n with HorizontalAlignment=Stretch will not actually grow.\n Override to Stretch to let the search box fill the content area. --\u003E\n \u003CHorizontalAlignment x:Key=\u0022TitleBarContentHorizontalAlignment\u0022\u003EStretch\u003C/HorizontalAlignment\u003E\n \u003C/TitleBar.Resources\u003E\n \u003CTitleBar.Content\u003E\n \u003CGrid ColumnSpacing=\u00228\u0022 HorizontalAlignment=\u0022Stretch\u0022\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022*\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022Auto\u0022 /\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003C!-- Interactive: auto-excluded from drag. --\u003E\n \u003CAutoSuggestBox\n MaxWidth=\u0022580\u0022\n HorizontalAlignment=\u0022Stretch\u0022\n VerticalAlignment=\u0022Center\u0022\n PlaceholderText=\u0022Search...\u0022\n QueryIcon=\u0022Find\u0022 /\u003E\n \u003C!-- Interactive Button. Drag behavior is overridden via\n TitleBar.IsDragRegion in code-behind. --\u003E\n \u003CButton\n x:Name=\u0022StatusBadge\u0022\n Grid.Column=\u00221\u0022\n VerticalAlignment=\u0022Center\u0022\n Click=\u0022StatusBadge_Click\u0022\n Content=\u0022Status\u0022\n Style=\u0022{StaticResource AccentButtonStyle}\u0022 /\u003E\n \u003C/Grid\u003E\n \u003C/TitleBar.Content\u003E\n\u003C/TitleBar\u003E",
+ "code": "// Set TitleBar.IsDragRegion at runtime.\nTitleBar.SetIsDragRegion(StatusBadge, true); // always draggable\nTitleBar.SetIsDragRegion(StatusBadge, false); // always clickable\nStatusBadge.ClearValue(TitleBar.IsDragRegionProperty); // back to default\n\n// After adding or removing elements in TitleBar.Content dynamically,\n// ask the framework to recompute drag regions.\ntitleBar.RecomputeDragRegions();",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TitlebarDragRegions.txt",
+ "source": "WinUIGallery/Samples/TitleBar/TitlebarDragRegions.txt",
+ "name": "Drag Regions"
+ }
+ },
+ {
+ "header": "End to end TitleBar sample",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.RowDefinitions\u003E\n \u003CRowDefinition Height=\u0022Auto\u0022 /\u003E\n \u003C!-- TitleBar --\u003E\n \u003CRowDefinition Height=\u0022*\u0022 /\u003E\n \u003C!-- NavigationView --\u003E\n \u003C/Grid.RowDefinitions\u003E\n\n \u003CTitleBar\n x:Name=\u0022titleBar\u0022\n BackRequested=\u0022TitleBar_BackRequested\u0022\n IsBackButtonVisible=\u0022{x:Bind navFrame.CanGoBack, Mode=OneWay}\u0022\n IsPaneToggleButtonVisible=\u0022True\u0022\n PaneToggleRequested=\u0022TitleBar_PaneToggleRequested\u0022 /\u003E\n\n \u003CNavigationView\n x:Name=\u0022navView\u0022\n Grid.Row=\u00221\u0022\n IsBackButtonVisible=\u0022Collapsed\u0022\n IsPaneToggleButtonVisible=\u0022False\u0022\u003E\n \u003CNavigationView.MenuItems... /\u003E\n \u003CFrame x:Name=\u0022navFrame\u0022 /\u003E\n \u003C/NavigationView\u003E\n\u003C/Grid\u003E",
+ "code": "this.ExtendsContentIntoTitleBar = true; // Extend the content into the title bar and hide the default titlebar\n this.SetTitleBar(titleBar); // Set the custom title bar",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "EndEndTitlebarSample.txt",
+ "source": "WinUIGallery/Samples/TitleBar/EndEndTitlebarSample.txt",
+ "name": "End End Titlebar Sample"
+ }
+ }
+ ]
+ },
+ {
+ "id": "togglebutton",
+ "name": "ToggleButton",
+ "description": "A button that can be switched between two states like a CheckBox.",
+ "details": "A ToggleButton looks like a Button, but works like a CheckBox. It typically has two states, checked (on) or unchecked (off), but can be indeterminate if the IsThreeState property is true. You can determine it\u0027s state by checking the IsChecked property.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls.Primitives",
+ "relatedControls": [
+ "Button",
+ "AppBarToggleButton",
+ "ToggleSwitch",
+ "CheckBox",
+ "CommandBarFlyout",
+ "CommandBar"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "curatedKeywords": [
+ "on off"
+ ],
+ "docs": [
+ {
+ "title": "ToggleButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.primitives.togglebutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons#create-a-toggle-split-button"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ToggleButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/ToggleButton/ToggleButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ToggleButton/ToggleButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "ButtonBase"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#CheckBox",
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#CommandBarFlyout",
+ "microsoft/WinUI-Gallery#ToggleSwitch"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple ToggleButton with text content.",
+ "xaml": "\u003CToggleButton Content=\u0022ToggleButton\u0022 Click=\u0022Button_Click\u0022 /\u003E",
+ "gallery": {
+ "snippet": "ToggleButtonSimple.txt",
+ "source": "WinUIGallery/Samples/ToggleButton/ToggleButtonSimple.txt",
+ "name": "Simple"
+ }
+ }
+ ]
+ },
+ {
+ "id": "togglesplitbutton",
+ "name": "ToggleSplitButton",
+ "description": "A version of the SplitButton where the activation target toggles on/off.",
+ "details": "A version of the SplitButton where the activation target toggles on/off.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "SplitButton",
+ "DropDownButton",
+ "Button",
+ "ToggleButton",
+ "ToggleSwitch",
+ "CheckBox"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "SplitButton"
+ ],
+ "curatedKeywords": [
+ "toggle split",
+ "dropdown toggle"
+ ],
+ "docs": [
+ {
+ "title": "ToggleSplitButton - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.togglesplitbutton"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/buttons"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ToggleSplitButton",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/ToggleSplitButton/ToggleSplitButtonPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ToggleSplitButton/ToggleSplitButtonPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl",
+ "SplitButton"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Button",
+ "microsoft/WinUI-Gallery#CheckBox",
+ "microsoft/WinUI-Gallery#DropDownButton",
+ "microsoft/WinUI-Gallery#SplitButton",
+ "microsoft/WinUI-Gallery#ToggleButton",
+ "microsoft/WinUI-Gallery#ToggleSwitch"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Using ToggleSplitButton to control bulleted list functionality in RichEditBox",
+ "xaml": "\u003CToggleSplitButton x:Name=\u0022myListButton\u0022 VerticalAlignment=\u0022Top\u0022 Click=\u0022myListButton_Click\u0022\u003E\n \u003CSymbolIcon x:Name=\u0022mySymbolIcon\u0022 Symbol=\u0022List\u0022/\u003E\n \u003CToggleSplitButton.Flyout\u003E\n \u003CFlyout Placement=\u0022Bottom\u0022\u003E\n \u003C!-- flyout content --\u003E\n \u003C/Flyout\u003E\n \u003C/ToggleSplitButton.Flyout\u003E\n\u003C/ToggleSplitButton\u003E",
+ "gallery": {
+ "snippet": "ToggleSplitButtonBulletList.txt",
+ "source": "WinUIGallery/Samples/ToggleSplitButton/ToggleSplitButtonBulletList.txt",
+ "name": "Bullet List"
+ }
+ }
+ ]
+ },
+ {
+ "id": "toggleswitch",
+ "name": "ToggleSwitch",
+ "description": "A switch that can be toggled between 2 states.",
+ "details": "Use ToggleSwitch controls to present users with exactly two mutually exclusive options (like on/off), where choosing an option results in an immediate commit. A toggle switch should have a single label.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ToggleButton",
+ "RadioButton",
+ "CheckBox",
+ "AppBarToggleButton"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "on off"
+ ],
+ "docs": [
+ {
+ "title": "ToggleSwitch - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.toggleswitch"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/toggles"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ToggleSwitch",
+ "group": {
+ "id": "BasicInput",
+ "title": "Basic input"
+ },
+ "page": "WinUIGallery/Samples/ToggleSwitch/ToggleSwitchPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ToggleSwitch/ToggleSwitchPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#CheckBox",
+ "microsoft/WinUI-Gallery#RadioButton",
+ "microsoft/WinUI-Gallery#ToggleButton"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple ToggleSwitch.",
+ "xaml": "\u003CToggleSwitch AutomationProperties.Name=\u0022simple ToggleSwitch\u0022/\u003E",
+ "gallery": {
+ "snippet": "ToggleSwitchSimple.txt",
+ "source": "WinUIGallery/Samples/ToggleSwitch/ToggleSwitchSimple.txt",
+ "name": "Simple"
+ }
+ },
+ {
+ "header": "A ToggleSwitch with custom header and content.",
+ "xaml": "\u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CToggleSwitch Header=\u0022Toggle work\u0022 OffContent=\u0022Do work\u0022 OnContent=\u0022Working\u0022 /\u003E\n \u003CProgressRing IsActive=\u0022{x:Bind ToggleSwitch2.IsOn, Mode=OneWay}\u0022 Width=\u002232\u0022/\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "ToggleSwitchCustom.txt",
+ "source": "WinUIGallery/Samples/ToggleSwitch/ToggleSwitchCustom.txt",
+ "name": "Custom",
+ "xamlPlaceholdersDropped": [
+ "isOff"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "tooltip",
+ "name": "ToolTip",
+ "description": "Displays information for an element in a pop-up window.",
+ "details": "A ToolTip shows more information about a UI element. You might show information about what the element does, or what the user should do. The ToolTip is shown when a user hovers over or presses and holds the UI element.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "TeachingTip",
+ "Flyout",
+ "ContentDialog"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "curatedKeywords": [
+ "hint",
+ "hover text"
+ ],
+ "docs": [
+ {
+ "title": "ToolTip - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.tooltip"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/tooltips"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "ToolTip",
+ "group": {
+ "id": "StatusAndInfo",
+ "title": "Status \u0026 info"
+ },
+ "page": "WinUIGallery/Samples/ToolTip/ToolTipPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/ToolTip/ToolTipPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control",
+ "ContentControl"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ContentDialog",
+ "microsoft/WinUI-Gallery#Flyout",
+ "microsoft/WinUI-Gallery#TeachingTip"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A button with a simple ToolTip.",
+ "xaml": "\u003CButton Content=\u0022Button with a simple ToolTip.\u0022 ToolTipService.ToolTip=\u0022Simple ToolTip\u0022/\u003E",
+ "gallery": {
+ "snippet": "ButtonSimpleTooltip.txt",
+ "source": "WinUIGallery/Samples/ToolTip/ButtonSimpleTooltip.txt",
+ "name": "Button Simple Tooltip"
+ }
+ },
+ {
+ "header": "A TextBlock with an offset ToolTip.",
+ "xaml": "\u003CTextBlock Text=\u0022TextBlock with an offset ToolTip.\u0022\u003E\n \u003CToolTipService.ToolTip\u003E\n \u003CToolTip Content=\u0022Offset ToolTip.\u0022 VerticalOffset=\u0022-80\u0022/\u003E\n \u003C/ToolTipService.ToolTip\u003E\n\u003C/TextBlock\u003E",
+ "gallery": {
+ "snippet": "TextblockOffsetTooltip.txt",
+ "source": "WinUIGallery/Samples/ToolTip/TextblockOffsetTooltip.txt",
+ "name": "Textblock Offset Tooltip"
+ }
+ },
+ {
+ "header": "An Image with a ToolTip using PlacementRect.",
+ "xaml": "\u003CImage Source=\u0022/Assets/SampleMedia/cliff.jpg\u0022 Width=\u0022400\u0022 Height=\u0022266\u0022\u003E\n \u003CToolTipService.ToolTip\u003E\n \u003CToolTip Content=\u0022Non-occluding ToolTip.\u0022 PlacementRect=\u00220,0,400,266\u0022/\u003E\n \u003C/ToolTipService.ToolTip\u003E\n\u003C/Image\u003E",
+ "gallery": {
+ "snippet": "ImageTooltipPlacementrect.txt",
+ "source": "WinUIGallery/Samples/ToolTip/ImageTooltipPlacementrect.txt",
+ "name": "Image Tooltip Placementrect"
+ }
+ }
+ ]
+ },
+ {
+ "id": "treeview",
+ "name": "TreeView",
+ "description": "The TreeView control is a hierarchical list pattern with expanding and collapsing nodes that contain nested items.",
+ "details": "The TreeView control is a hierarchical list pattern with expanding and collapsing nodes that contain nested items. ",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ListView",
+ "ItemsRepeater"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "System.Collections.ObjectModel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "curatedKeywords": [
+ "tree",
+ "hierarchy",
+ "nodes",
+ "expandable list"
+ ],
+ "docs": [
+ {
+ "title": "TreeView - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.Controls.TreeView"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/tree-view"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "TreeView",
+ "group": {
+ "id": "Collections",
+ "title": "Collections"
+ },
+ "page": "WinUIGallery/Samples/TreeView/TreeViewPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/TreeView/TreeViewPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Control"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#ListView"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple TreeView with drag and drop support",
+ "xaml": "\u003CTreeView x:Name=\u0022sampleTreeView\u0022 CanDragItems=\u0022True\u0022 AllowDrop=\u0022True\u0022/\u003E",
+ "code": "private void InitializeSampleTreeView(TreeView sampleTreeView)\n{\n // Create a root node with initial content and set it to be expanded.\n TreeViewNode workNode = new TreeViewNode() { Content = \u0022Work Documents\u0022 };\n workNode.IsExpanded = true;\n\n // Add child nodes with content related to the root node.\n workNode.Children.Add(new TreeViewNode() { Content = \u0022XYZ Functional Spec\u0022 });\n workNode.Children.Add(new TreeViewNode() { Content = \u0022Feature Schedule\u0022 });\n\n // Create another node with initial content and set it to be expanded.\n TreeViewNode remodelNode = new TreeViewNode() { Content = \u0022Home Remodel\u0022 };\n remodelNode.IsExpanded = true;\n\n // Add child nodes with specific content under this node.\n remodelNode.Children.Add(new TreeViewNode() { Content = \u0022Contractor Contact Info\u0022 });\n remodelNode.Children.Add(new TreeViewNode() { Content = \u0022Paint Color Scheme\u0022 });\n\n // Create a node with broader content that includes the previous node as a child.\n TreeViewNode personalNode = new TreeViewNode() { Content = \u0022Personal Documents\u0022 };\n personalNode.IsExpanded = true;\n personalNode.Children.Add(remodelNode);\n\n // Add the main nodes to the TreeView\u0027s root.\n sampleTreeView.RootNodes.Add(workNode);\n sampleTreeView.RootNodes.Add(personalNode);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "SimpleTreeviewDragDrop.txt",
+ "source": "WinUIGallery/Samples/TreeView/SimpleTreeviewDragDrop.txt",
+ "name": "Simple Treeview Drag Drop"
+ }
+ },
+ {
+ "header": "A TreeView with Multi-selection enabled",
+ "xaml": "\u003CTreeView x:Name=\u0022sampleTreeView\u0022 SelectionMode=\u0022Multiple\u0022 /\u003E",
+ "code": "private void InitializeSampleTreeView(TreeView sampleTreeView)\n{\n // Create a root node with initial content and set it to be expanded.\n TreeViewNode workNode = new TreeViewNode() { Content = \u0022Work Documents\u0022 };\n workNode.IsExpanded = true;\n\n // Add child nodes with content related to the root node.\n workNode.Children.Add(new TreeViewNode() { Content = \u0022XYZ Functional Spec\u0022 });\n workNode.Children.Add(new TreeViewNode() { Content = \u0022Feature Schedule\u0022 });\n\n // Create another node with initial content and set it to be expanded.\n TreeViewNode remodelNode = new TreeViewNode() { Content = \u0022Home Remodel\u0022 };\n remodelNode.IsExpanded = true;\n\n // Add child nodes with specific content under this node.\n remodelNode.Children.Add(new TreeViewNode() { Content = \u0022Contractor Contact Info\u0022 });\n remodelNode.Children.Add(new TreeViewNode() { Content = \u0022Paint Color Scheme\u0022 });\n\n // Create a node with broader content that includes the previous node as a child.\n TreeViewNode personalNode = new TreeViewNode() { Content = \u0022Personal Documents\u0022 };\n personalNode.IsExpanded = true;\n personalNode.Children.Add(remodelNode);\n\n // Add the main nodes to the TreeView\u0027s root.\n sampleTreeView.RootNodes.Add(workNode);\n sampleTreeView.RootNodes.Add(personalNode);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TreeviewMultiSelectionEnabled.txt",
+ "source": "WinUIGallery/Samples/TreeView/TreeviewMultiSelectionEnabled.txt",
+ "name": "Multi Selection Enabled"
+ }
+ },
+ {
+ "header": "A TreeView with DataBinding Using ItemSource",
+ "code": "using System.Collections.ObjectModel;\nusing Microsoft.UI.Xaml;\nusing Microsoft.UI.Xaml.Controls;\n\nnamespace YourNamespace\n{\n public sealed partial class YourPage : Page\n {\n // DataSource is the data collection that will be bound to the TreeView\u0027s ItemsSource.\n public ObservableCollection\u003CExplorerItem\u003E DataSource { get; set; }\n\n public YourPage()\n {\n this.InitializeComponent();\n\n // Initialize the data source with sample data and set it as the context for data binding.\n DataSource = GetData();\n this.DataContext = this; // Bind the DataContext of the page to itself for XAML bindings.\n }\n\n // Method to provide sample data for the TreeView.\n private ObservableCollection\u003CExplorerItem\u003E GetData()\n {\n return new ObservableCollection\u003CExplorerItem\u003E\n {\n // Root folder with child files.\n new ExplorerItem\n {\n Name = \u0022Documents\u0022,\n Type = ExplorerItem.ExplorerItemType.Folder,\n Children =\n {\n new ExplorerItem\n {\n Name = \u0022ProjectProposal\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n new ExplorerItem\n {\n Name = \u0022BudgetReport\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n },\n },\n // Another root folder with one child file.\n new ExplorerItem\n {\n Name = \u0022Projects\u0022,\n Type = ExplorerItem.ExplorerItemType.Folder,\n Children =\n {\n new ExplorerItem\n {\n Name = \u0022Project Plan\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n },\n },\n };\n }\n }\n\n // Class to represent items in the TreeView.\n public class ExplorerItem\n {\n // Enum to define the type of the item: Folder or File.\n public enum ExplorerItemType\n {\n Folder,\n File,\n }\n\n // Name of the item (displayed in the TreeView).\n public string Name { get; set; } = string.Empty;\n\n // Type of the item (Folder or File).\n public ExplorerItemType Type { get; set; }\n\n // Collection of child items. Used for nested nodes in the TreeView.\n public ObservableCollection\u003CExplorerItem\u003E Children { get; set; } = new ObservableCollection\u003CExplorerItem\u003E();\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TreeviewDatabindingItemsource.txt",
+ "source": "WinUIGallery/Samples/TreeView/TreeviewDatabindingItemsource.txt",
+ "name": "Databinding Itemsource",
+ "xamlOmittedUnboundPrefixes": [
+ "local"
+ ]
+ }
+ },
+ {
+ "header": "A TreeView with ItemTemplateSelector",
+ "code": "using System.Collections.ObjectModel;\nusing Microsoft.UI.Xaml;\nusing Microsoft.UI.Xaml.Controls;\n\nnamespace YourNamespace\n{\n public sealed partial class YourPage : Page\n {\n public ObservableCollection\u003CExplorerItem\u003E DataSource { get; set; }\n\n public YourPage()\n {\n this.InitializeComponent();\n DataSource = GetData();\n this.DataContext = this;\n }\n\n private ObservableCollection\u003CExplorerItem\u003E GetData()\n {\n return new ObservableCollection\u003CExplorerItem\u003E\n {\n new ExplorerItem\n {\n Name = \u0022Documents\u0022,\n Type = ExplorerItem.ExplorerItemType.Folder,\n Children =\n {\n new ExplorerItem\n {\n Name = \u0022ProjectProposal\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n new ExplorerItem\n {\n Name = \u0022BudgetReport\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n },\n },\n new ExplorerItem\n {\n Name = \u0022Projects\u0022,\n Type = ExplorerItem.ExplorerItemType.Folder,\n Children =\n {\n new ExplorerItem\n {\n Name = \u0022Project Plan\u0022,\n Type = ExplorerItem.ExplorerItemType.File,\n },\n },\n },\n };\n }\n }\n\n public class ExplorerItem\n {\n public enum ExplorerItemType\n {\n Folder,\n File,\n }\n\n public string Name { get; set; } = string.Empty;\n public ExplorerItemType Type { get; set; }\n public ObservableCollection\u003CExplorerItem\u003E Children { get; set; } = new ObservableCollection\u003CExplorerItem\u003E();\n }\n\n class ExplorerItemTemplateSelector : DataTemplateSelector\n {\n // Template to use for folder items in the TreeView.\n public DataTemplate? FolderTemplate { get; set; }\n\n // Template to use for file items in the TreeView.\n public DataTemplate? FileTemplate { get; set; }\n\n // Determines which template to use for each item in the TreeView based on its type.\n protected override DataTemplate? SelectTemplateCore(object item)\n {\n // Cast the item to the ExplorerItem type.\n var explorerItem = (ExplorerItem)item;\n\n // Return the appropriate template: FolderTemplate for folders, FileTemplate for files.\n return explorerItem.Type == ExplorerItem.ExplorerItemType.Folder\n ? FolderTemplate\n : FileTemplate;\n }\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "TreeviewItemtemplateselector.txt",
+ "source": "WinUIGallery/Samples/TreeView/TreeviewItemtemplateselector.txt",
+ "name": "Itemtemplateselector",
+ "xamlOmittedAsMalformed": true
+ }
+ }
+ ]
+ },
+ {
+ "id": "typography",
+ "name": "Typography",
+ "description": "Typography design guides attention with intuitive fonts and hierarchy.",
+ "curatedKeywords": [
+ "font",
+ "text style",
+ "TitleTextBlockStyle",
+ "BodyTextBlockStyle",
+ "font size"
+ ],
+ "docs": [
+ {
+ "title": "Typography in Windows Apps",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/typography"
+ },
+ {
+ "title": "XAML theme resources",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/xaml-theme-resources#the-xaml-type-ramp"
+ },
+ {
+ "title": "Typography in Windows 11",
+ "uri": "https://learn.microsoft.com/windows/apps/design/signature-experiences/typography"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Typography",
+ "group": {
+ "id": "DesignItem",
+ "title": "Design"
+ },
+ "page": "WinUIGallery/Samples/Typography/TypographyPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Typography/TypographyPage.xaml.cs"
+ },
+ "samples": [
+ {
+ "header": "Type ramp",
+ "xaml": "\u003CTextBlock Text=\u0022Caption\u0022 Style=\u0022{StaticResource CaptionTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Body\u0022 Style=\u0022{StaticResource BodyTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Body Strong\u0022 Style=\u0022{StaticResource BodyStrongTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Body Large\u0022 Style=\u0022{StaticResource BodyLargeTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Body Strong Strong\u0022 Style=\u0022{StaticResource BodyLargeStrongTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Subtitle\u0022 Style=\u0022{StaticResource SubtitleTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Title\u0022 Style=\u0022{StaticResource TitleTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Title Large\u0022 Style=\u0022{StaticResource TitleLargeTextBlockStyle}\u0022/\u003E\n\u003CTextBlock Text=\u0022Display\u0022 Style=\u0022{StaticResource DisplayTextBlockStyle}\u0022/\u003E",
+ "gallery": {
+ "snippet": "TypographyTypeRamp.txt",
+ "source": "WinUIGallery/Samples/Typography/TypographyTypeRamp.txt",
+ "name": "Type Ramp"
+ }
+ }
+ ]
+ },
+ {
+ "id": "variablesizedwrapgrid",
+ "name": "VariableSizedWrapGrid",
+ "description": "A layout panel that supports arranging child elements in rows and columns. Each child element can span multiple rows and columns.",
+ "details": "A VariableSizedWrapGrip is used to create grid layouts where content can span multiple rows and columns.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "Border",
+ "Canvas",
+ "Grid",
+ "StackPanel",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "wrap grid",
+ "tiles",
+ "spanning"
+ ],
+ "docs": [
+ {
+ "title": "VariableSizedWrapGrid - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.variablesizedwrapgrid"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/layout/layout-panels"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "VariableSizedWrapGrid",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/VariableSizedWrapGrid/VariableSizedWrapGridPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/VariableSizedWrapGrid/VariableSizedWrapGridPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Border",
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#StackPanel"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A VariableSizedWrapGrid control.",
+ "xaml": "\u003CVariableSizedWrapGrid MaximumRowsOrColumns=\u00223\u0022 ItemHeight=\u002244\u0022 ItemWidth=\u002244\u0022\u003E\n \u003CRectangle Fill=\u0022Red\u0022/\u003E\n \u003CRectangle Fill=\u0022Blue\u0022 Height=\u002280\u0022 VariableSizedWrapGrid.RowSpan=\u00222\u0022/\u003E\n \u003CRectangle Fill=\u0022Green\u0022 Width=\u002280\u0022 VariableSizedWrapGrid.ColumnSpan=\u00222\u0022/\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022 Height=\u002280\u0022 Width=\u002280\u0022 VariableSizedWrapGrid.RowSpan=\u00222\u0022 VariableSizedWrapGrid.ColumnSpan=\u00222\u0022/\u003E\n\u003C/VariableSizedWrapGrid\u003E",
+ "gallery": {
+ "snippet": "VariablesizedwrapgridControl.txt",
+ "source": "WinUIGallery/Samples/VariableSizedWrapGrid/VariablesizedwrapgridControl.txt",
+ "name": "Control",
+ "xamlPlaceholdersDropped": [
+ "Orientation"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "viewbox",
+ "name": "Viewbox",
+ "description": "A container control that scales its content to a specified size.",
+ "details": "Use a Viewbox control scale content up or down to a specified size.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "ScrollViewer",
+ "Canvas",
+ "Grid",
+ "StackPanel",
+ "RelativePanel"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "scale",
+ "stretch",
+ "zoom content"
+ ],
+ "docs": [
+ {
+ "title": "Viewbox - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.Viewbox"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Viewbox",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/Viewbox/ViewboxPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Viewbox/ViewboxPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Canvas",
+ "microsoft/WinUI-Gallery#Grid",
+ "microsoft/WinUI-Gallery#RelativePanel",
+ "microsoft/WinUI-Gallery#ScrollViewer",
+ "microsoft/WinUI-Gallery#StackPanel"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Content inside of a Viewbox.",
+ "xaml": "\u003CViewbox Height=\u0022200\u0022 Width=\u0022200\u0022 StretchDirection=\u0022Both\u0022\u003E\n \u003CBorder BorderBrush=\u0022Gray\u0022 BorderThickness=\u002215\u0022\u003E\n \u003CStackPanel Background=\u0022DarkGray\u0022\u003E\n \u003CStackPanel Orientation=\u0022Horizontal\u0022\u003E\n \u003CRectangle Fill=\u0022Blue\u0022 Height=\u002210\u0022 Width=\u002240\u0022/\u003E\n \u003CRectangle Fill=\u0022Green\u0022 Height=\u002210\u0022 Width=\u002240\u0022/\u003E\n \u003CRectangle Fill=\u0022Red\u0022 Height=\u002210\u0022 Width=\u002240\u0022/\u003E\n \u003CRectangle Fill=\u0022Yellow\u0022 Height=\u002210\u0022 Width=\u002240\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003CImage Source=\u0022ms-appx:///Assets/SampleMedia/Slices.png\u0022/\u003E\n \u003CTextBlock Text=\u0022This is text.\u0022 HorizontalAlignment=\u0022Center\u0022/\u003E\n \u003C/StackPanel\u003E\n \u003C/Border\u003E\n\u003C/Viewbox\u003E",
+ "gallery": {
+ "snippet": "ContentInsideViewbox.txt",
+ "source": "WinUIGallery/Samples/Viewbox/ContentInsideViewbox.txt",
+ "name": "Content Inside Viewbox",
+ "xamlPlaceholdersDropped": [
+ "Stretch"
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "id": "webview2",
+ "name": "WebView2",
+ "description": "A Microsoft Edge (Chromium) based control that hosts HTML content in an app.",
+ "details": "A Microsoft Edge (Chromium) based control that hosts HTML content in an app.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ],
+ "curatedKeywords": [
+ "browser",
+ "HTML",
+ "Edge",
+ "web content"
+ ],
+ "docs": [
+ {
+ "title": "WebView2 - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.webview2"
+ },
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/microsoft-edge/webview2/gettingstarted/winui"
+ },
+ {
+ "title": "Examples",
+ "uri": "https://github.com/MicrosoftEdge/WebView2Samples"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "WebView2",
+ "group": {
+ "id": "Media",
+ "title": "Media"
+ },
+ "page": "WinUIGallery/Samples/WebView2/WebView2Page.xaml",
+ "codeBehind": "WinUIGallery/Samples/WebView2/WebView2Page.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A simple WebView2",
+ "xaml": "\u003CWebView2 x:Name=\u0022MyWebView2\u0022 Source=\u0022https://learn.microsoft.com/windows/apps/winui/winui3/\u0022 HorizontalAlignment=\u0022Stretch\u0022 VerticalAlignment=\u0022Stretch\u0022 Grid.Row=\u00221\u0022 MinHeight=\u0022200\u0022 MinWidth=\u0022200\u0022/\u003E",
+ "gallery": {
+ "snippet": "SimpleWebview2.txt",
+ "source": "WinUIGallery/Samples/WebView2/SimpleWebview2.txt",
+ "name": "Simple Webview2"
+ }
+ }
+ ]
+ },
+ {
+ "id": "windowing",
+ "name": "Window",
+ "description": "Create top-level XAML windows and configure their client-area size.",
+ "details": "Create single-threaded top-level XAML windows, then explore experimental client-area sizing and minimum/maximum limits.",
+ "apiNamespace": "Microsoft.UI.Xaml",
+ "relatedControls": [
+ "AppWindow",
+ "AppWindowTitleBar",
+ "TitleBar"
+ ],
+ "usings": [
+ "Microsoft.UI.Windowing",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Media",
+ "Windows.Graphics"
+ ],
+ "curatedKeywords": [
+ "multiple windows",
+ "new window",
+ "multi window",
+ "experimental",
+ "window sizing",
+ "client area",
+ "DIPs",
+ "Width",
+ "Height",
+ "MinWidth",
+ "MinHeight",
+ "MaxWidth",
+ "MaxHeight"
+ ],
+ "docs": [
+ {
+ "title": "Windows App SDK release channels",
+ "uri": "https://learn.microsoft.com/windows/apps/windows-app-sdk/release-channels"
+ },
+ {
+ "title": "Window - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window?view=windows-app-sdk-2.0-experimental"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "Windowing",
+ "group": {
+ "id": "MultipleWindows",
+ "title": "Windowing"
+ },
+ "page": "WinUIGallery/Samples/Windowing/WindowingPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/Windowing/WindowingPage.xaml.cs",
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppWindow",
+ "microsoft/WinUI-Gallery#AppWindowTitleBar",
+ "microsoft/WinUI-Gallery#TitleBar"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Create a single-threaded top-level Window.",
+ "code": "Window childWindow = new Window\n{\n ExtendsContentIntoTitleBar = true,\n SystemBackdrop = new MicaBackdrop(),\n Content = new TextBlock\n {\n Text = \u0022New child window!\u0022,\n HorizontalAlignment = HorizontalAlignment.Center,\n VerticalAlignment = VerticalAlignment.Center,\n RequestedTheme = ActualTheme\n }\n};\n\n// Gallery tracks child windows so they close when the app closes.\nWindowHelper.TrackWindow(childWindow);\n// ResizeClient takes physical pixels, independent of display scaling.\nchildWindow.AppWindow.ResizeClient(new SizeInt32(500, 500));\nchildWindow.Activate();",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CreateMultipleWindows.txt",
+ "source": "WinUIGallery/Samples/Windowing/CreateMultipleWindows.txt",
+ "name": "Create Multiple Windows"
+ }
+ },
+ {
+ "header": "Configure the client size and constraints",
+ "xaml": "\u003C!-- SampleWindow.xaml; keep the template\u0027s InitializeComponent() constructor. --\u003E\n\u003CWindow\n x:Class=\u0022MyApp.SampleWindow\u0022\n xmlns=\u0022http://schemas.microsoft.com/winfx/2006/xaml/presentation\u0022\n xmlns:x=\u0022http://schemas.microsoft.com/winfx/2006/xaml\u0022\n Width=\u0022640\u0022\n Height=\u0022480\u0022\n MinWidth=\u0022320\u0022\n MinHeight=\u0022240\u0022\n MaxWidth=\u0022960\u0022\n MaxHeight=\u0022720\u0022\u003E\n \u003CTextBlock Margin=\u002224\u0022 Text=\u0022Resize this window.\u0022 /\u003E\n\u003C/Window\u003E",
+ "code": "// The same size properties can be set in C# instead of XAML.\nWindow window = new Window\n{\n Width = 640,\n Height = 480,\n MinWidth = 320,\n MinHeight = 240,\n MaxWidth = 960,\n MaxHeight = 720,\n Content = new TextBlock { Margin = new Thickness(24), Text = \u0022Resize this window.\u0022 }\n};\n\nif (window.AppWindow.Presenter is OverlappedPresenter presenter)\n{\n presenter.IsMaximizable = false;\n}\n\n// Gallery tracks child windows so they close when the app closes.\nWindowHelper.TrackWindow(window);\n// Use Window.Activate() for the first show, including for XAML-defined windows.\nwindow.Activate();",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "WindowSizing.txt",
+ "source": "WinUIGallery/Samples/Windowing/WindowSizing.txt",
+ "name": "Window Sizing"
+ }
+ }
+ ]
+ },
+ {
+ "id": "wrappanel",
+ "name": "WrapPanel",
+ "description": "A layout panel that arranges child elements in rows or columns and automatically wraps them onto new lines.",
+ "details": "Use a WrapPanel to arrange child elements sequentially and move overflowing items to a new row or column. You can configure its orientation, spacing, padding, and whether the final item stretches to fill the remaining space.",
+ "apiNamespace": "Microsoft.UI.Xaml.Controls",
+ "relatedControls": [
+ "StackPanel",
+ "VariableSizedWrapGrid",
+ "ItemsRepeater",
+ "GridView"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "curatedKeywords": [
+ "wrap",
+ "responsive layout",
+ "flow layout",
+ "spacing"
+ ],
+ "gallery": {
+ "uniqueId": "WrapPanel",
+ "group": {
+ "id": "Layout",
+ "title": "Layout"
+ },
+ "page": "WinUIGallery/Samples/WrapPanel/WrapPanelPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/WrapPanel/WrapPanelPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject",
+ "UIElement",
+ "FrameworkElement",
+ "Panel"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#GridView",
+ "microsoft/WinUI-Gallery#ItemsRepeater",
+ "microsoft/WinUI-Gallery#StackPanel",
+ "microsoft/WinUI-Gallery#VariableSizedWrapGrid"
+ ]
+ },
+ "samples": [
+ {
+ "header": "A WrapPanel that automatically wraps items when they reach the panel boundary.",
+ "xaml": "\u003CWrapPanel\n Width=\u0022360\u0022\n Height=\u0022200\u0022\n ItemSpacing=\u00228\u0022\n LineSpacing=\u00228\u0022\n Padding=\u002212\u0022\u003E\n \u003CBorder MinWidth=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Alpha\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u0022112\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Beta item\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u002288\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Gamma\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u0022128\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Delta item\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u002280\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Epsilon\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u0022104\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Zeta item\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u002276\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Eta\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u0022120\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Theta item\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u002292\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Iota\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder MinWidth=\u0022132\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Kappa item\u0022/\u003E\n \u003C/Border\u003E\n\u003C/WrapPanel\u003E",
+ "gallery": {
+ "snippet": "WrapPanelBasic.txt",
+ "source": "WinUIGallery/Samples/WrapPanel/WrapPanelBasic.txt",
+ "name": "Basic",
+ "xamlPlaceholdersDropped": [
+ "Orientation"
+ ]
+ }
+ },
+ {
+ "header": "A WrapPanel that can stretch its final item to fill the remaining space.",
+ "xaml": "\u003CWrapPanel\n Width=\u0022360\u0022\n ItemSpacing=\u00228\u0022\n ItemsStretch=\u0022Last\u0022\n Padding=\u002212\u0022\u003E\n \u003CBorder Width=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022One\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Width=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Two\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Width=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Three\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Width=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Four\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Width=\u002272\u0022 Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Five\u0022/\u003E\n \u003C/Border\u003E\n \u003CBorder Padding=\u002212,8\u0022\u003E\n \u003CTextBlock Text=\u0022Final item\u0022/\u003E\n \u003C/Border\u003E\n\u003C/WrapPanel\u003E",
+ "gallery": {
+ "snippet": "WrapPanelItemsStretch.txt",
+ "source": "WinUIGallery/Samples/WrapPanel/WrapPanelItemsStretch.txt",
+ "name": "Items Stretch"
+ }
+ }
+ ]
+ },
+ {
+ "id": "xamlcompinterop",
+ "name": "Animation interop",
+ "description": "XAML and Composition interop allows you to animate elements using expressions, natural animations, and more.",
+ "details": "XAML and Composition interop allows you to animate elements using expressions, natural animations, and more",
+ "relatedControls": [
+ "Easing Functions"
+ ],
+ "usings": [
+ "Microsoft.UI.Composition",
+ "Microsoft.UI.Xaml",
+ "Microsoft.UI.Xaml.Automation",
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Controls.Primitives",
+ "Microsoft.UI.Xaml.Input",
+ "System",
+ "System.Globalization",
+ "System.Numerics"
+ ],
+ "curatedKeywords": [
+ "composition",
+ "Visual layer",
+ "expression animation",
+ "interop"
+ ],
+ "docs": [
+ {
+ "title": "Quickstart: Motion",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion"
+ },
+ {
+ "title": "Composition Animation - API",
+ "uri": "https://learn.microsoft.com/windows/apps/windows-app-sdk/composition"
+ },
+ {
+ "title": "Guidelines - Xaml Property Animations",
+ "uri": "https://learn.microsoft.com/windows/apps/design/motion/xaml-property-animations"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "XamlCompInterop",
+ "group": {
+ "id": "Motion",
+ "title": "Motion"
+ },
+ "page": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropPage.xaml.cs",
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#EasingFunction"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Use a natural motion composition animation on a UIElement",
+ "code": "Compositor _compositor = Microsoft.UI.Xaml.Media.CompositionTarget.GetCompositorForCurrentThread();\nSpringVector3NaturalMotionAnimation? _springAnimation;\n\nprivate void CreateOrUpdateSpringAnimation(float finalValue)\n{\n if (_springAnimation == null)\n {\n _springAnimation = _compositor.CreateSpringVector3Animation();\n _springAnimation.Target = \u0022Scale\u0022;\n }\n\n _springAnimation.FinalValue = new Vector3(finalValue);\n}\n\nprivate void element_PointerEntered(object sender, PointerRoutedEventArgs e)\n{\n // Scale up to 1.5\n CreateOrUpdateSpringAnimation(1.5f);\n\n (sender as UIElement)?.StartAnimation(_springAnimation);\n}\n\nprivate void element_PointerExited(object sender, PointerRoutedEventArgs e)\n{\n // Scale back down to 1.0\n CreateOrUpdateSpringAnimation(1.0f);\n\n (sender as UIElement)?.StartAnimation(_springAnimation);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "XamlCompInteropNaturalMotionCompositionAnimation.txt",
+ "source": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropNaturalMotionCompositionAnimation.txt",
+ "name": "Natural Motion Composition Animation"
+ }
+ },
+ {
+ "header": "ExpressionAnimation on an Ellipse element",
+ "xaml": "\u003CStackPanel Height=\u0022200\u0022\u003E\n \u003CGrid VerticalAlignment=\u0022Top\u0022\u003E\n \u003CGrid.ColumnDefinitions\u003E\n \u003CColumnDefinition Width=\u0022*\u0022 /\u003E\n \u003CColumnDefinition Width=\u0022*\u0022 /\u003E\n \u003C/Grid.ColumnDefinitions\u003E\n \u003CRectangle x:Name=\u0022rectangle\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Fill=\u0022{ThemeResource SystemAccentColor}\u0022 PointerEntered=\u0022element_PointerEntered\u0022 PointerExited=\u0022element_PointerExited\u0022 /\u003E\n \u003CEllipse x:Name=\u0022ellipse\u0022 Grid.Column=\u00221\u0022 Width=\u002250\u0022 Height=\u002250\u0022 Margin=\u002255,0\u0022 Fill=\u0022{ThemeResource SystemAccentColor}\u0022/\u003E\n \u003C/Grid\u003E\n\u003C/StackPanel\u003E",
+ "code": "// NOTE: The rectangle scales up and down using the same element_PointerEntered/Exited events as the prior sample.\n\nCompositor _compositor = Microsoft.UI.Xaml.Media.CompositionTarget.GetCompositorForCurrentThread();\n\n// Set up the relationship between the rectangle and the ellipse.\nprivate void ExpressionSample_Loaded(object sender, RoutedEventArgs e)\n{\n var expressionAnim = _compositor.CreateExpressionAnimation();\n\n // The ellipse\u0027s scale is inversely proportional to the rectangle\u0027s scale\n expressionAnim.Expression = \u0022Vector3(1/scaleElement.Scale.X, 1/scaleElement.Scale.Y, 1)\u0022;\n expressionAnim.Target = \u0022Scale\u0022;\n\n // Use SetExpressionReferenceParameter to alias a UIElement into the expression string\n expressionAnim.SetExpressionReferenceParameter(\u0022scaleElement\u0022, rectangle);\n\n // Start the animation on the ellipse\n ellipse.StartAnimation(expressionAnim);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "XamlCompInteropExpressionanimationEllipseElement.txt",
+ "source": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropExpressionanimationEllipseElement.txt",
+ "name": "Expressionanimation Ellipse Element"
+ }
+ },
+ {
+ "header": "Driving several related animations together using ExpressionAnimation",
+ "code": "// NOTE: Each of the buttons scale up and down using the same element_PointerEntered/Exited events as the prior samples.\n\nprivate void StackedButtonsExample_Loaded(object sender, RoutedEventArgs e)\n{\n // Animate the translation of each button relative to the scale and translation of the button above.\n var anim = _compositor.CreateExpressionAnimation();\n anim.Expression = \u0022(above.Scale.Y - 1) * 50 \u002B above.Translation.Y % (50 * index)\u0022;\n anim.Target = \u0022Translation.Y\u0022;\n\n // Animate the second button relative to the first.\n anim.SetExpressionReferenceParameter(\u0022above\u0022, ExpressionButton1);\n anim.SetScalarParameter(\u0022index\u0022, 1);\n ExpressionButton2.StartAnimation(anim);\n\n // Animate the third button relative to the second.\n anim.SetExpressionReferenceParameter(\u0022above\u0022, ExpressionButton2);\n anim.SetScalarParameter(\u0022index\u0022, 2);\n ExpressionButton3.StartAnimation(anim);\n\n // Animate the fourth button relative to the third.\n anim.SetExpressionReferenceParameter(\u0022above\u0022, ExpressionButton3);\n anim.SetScalarParameter(\u0022index\u0022, 3);\n ExpressionButton4.StartAnimation(anim);\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "XamlCompInteropDrivingSeveralRelatedAnimations.txt",
+ "source": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropDrivingSeveralRelatedAnimations.txt",
+ "name": "Driving Several Related Animations"
+ }
+ },
+ {
+ "header": "Reference ActualSize in ExpressionAnimations to make novel layouts based on size",
+ "code": "private void ActualSizeExample_Loaded(object sender, RoutedEventArgs e)\n{\n // We will lay out some buttons in a circle.\n // The formulas we will use are:\n // X = radius * cos(theta) \u002B xOffset\n // Y = radius * sin(theta) \u002B yOffset\n // radius = 1/2 the width and height of the parent container\n // theta = the angle for each element. The starting value of theta depends on both the number of elements and the relative index of each element.\n // xOffset = The starting horizontal offset for the element. \n // yOffset = The starting vertical offset for the element.\n\n String radius = \u0022(source.ActualSize.X / 2)\u0022; // Since the layout is a circle, width and height are equivalent meaning we could use X or Y. We\u0027ll use X.\n String theta = \u0022.02 * \u0022 \u002B radius \u002B \u0022 \u002B ((2 * Pi)/total)*index\u0022; // The first value is the rate of angular change based on radius. The last value spaces the buttons equally.\n String xOffset = radius; // We offset x by radius because the buttons naturally layout along the left edge. We need to move them to center of the circle first.\n String yOffset = \u00220\u0022; // We don\u0027t need to offset y because the buttons naturally layout vertically centered.\n\n // We combine X, Y, and Z subchannels into a single animation because we can only start a single animation on Translation.\n String expression = String.Format(\u0022Vector3({0}*cos({1})\u002B{2}, {0}*sin({1})\u002B{3},0)\u0022, radius, theta, xOffset, yOffset);\n\n int totalElements = 8;\n for (int i = 0; i \u003C totalElements; i\u002B\u002B)\n {\n Button element = new Button() { Content = \u0022Button\u0022 \u002B i };\n LayoutPanel.Children.Add(element);\n\n var anim = _compositor.CreateExpressionAnimation();\n\n anim.Expression = expression;\n anim.SetScalarParameter(\u0022index\u0022, i \u002B 1);\n anim.SetScalarParameter(\u0022total\u0022, totalElements);\n anim.Target = \u0022Translation\u0022;\n anim.SetExpressionReferenceParameter(\u0022source\u0022, LayoutPanel);\n\n element.StartAnimation(anim);\n }\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "XamlCompInteropReferenceActualsizeExpressionanimationsMake.txt",
+ "source": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropReferenceActualsizeExpressionanimationsMake.txt",
+ "name": "Reference Actualsize Expressionanimations Make"
+ }
+ },
+ {
+ "header": "Reference ActualOffset and ActualSize in ExpressionAnimations to position elements relative to each other",
+ "xaml": "\u003CGrid HorizontalAlignment=\u0022Left\u0022 Margin=\u00220,12,0,0\u0022\u003E\n \u003CTextBlock x:Name=\u0022PopupTarget\u0022 \n Width=\u0022300\u0022 \n TextWrapping=\u0022WrapWholeWords\u0022 \n Margin=\u0022{x:Bind MarginSlider.Value, Converter={StaticResource doubleToThicknessConverter}, Mode=OneWay}\u0022 \n FontSize=\u0022{x:Bind FontSizeSlider.Value, Mode=OneWay}\u0022 \n Text=\u0022... lorem ipsum ...\u0022 /\u003E\n\n \u003C!-- Notice that the popup is a sibling to the target, not an ancestor. --\u003E\n \u003CPopup x:Name=\u0022Popup\u0022 Margin=\u00225\u0022\u003E\n \u003CGrid MinWidth=\u002250\u0022 MaxWidth=\u0022200\u0022 MinHeight=\u002250\u0022 BorderBrush=\u0022LightGray\u0022 BorderThickness=\u00222\u0022 Background=\u0022{ThemeResource FlyoutBackgroundThemeBrush}\u0022\u003E\n \u003CTextBlock Text=\u0022I am always right aligned center to the target.\u0022 TextWrapping=\u0022WrapWholeWords\u0022 Margin=\u00226\u0022 FontSize=\u002212\u0022 VerticalAlignment=\u0022Center\u0022 /\u003E\n \u003C/Grid\u003E\n \u003C/Popup\u003E\n\u003C/Grid\u003E",
+ "code": "private void ActualOffsetExample_Loaded(object sender, RoutedEventArgs e)\n{\n // This sample positions a popup relative to a block of text that has variable layout size based on font size.\n var anim = _compositor.CreateExpressionAnimation();\n\n anim.Expression = \u0022Vector3(source.ActualOffset.X \u002B source.ActualSize.X, source.ActualOffset.Y \u002B source.ActualSize.Y / 2 - 25, 0)\u0022;\n anim.Target = \u0022Translation\u0022;\n anim.SetExpressionReferenceParameter(\u0022source\u0022, PopupTarget);\n\n Popup.StartAnimation(anim);\n\n Popup.IsOpen = true;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "XamlCompInteropReferenceActualoffsetActualsizeExpressionanimations.txt",
+ "source": "WinUIGallery/Samples/XamlCompInterop/XamlCompInteropReferenceActualoffsetActualsizeExpressionanimations.txt",
+ "name": "Reference Actualoffset Actualsize Expressionanimations"
+ }
+ }
+ ]
+ },
+ {
+ "id": "xamlresources",
+ "name": "Resources",
+ "description": "Reusable definitions for shared values to ensure consistency and maintainability.",
+ "details": "In WinUI 3, XAML resources are reusable objects like colors, brushes, or strings, defined once and used throughout your app to maintain consistency and simplify updates. These resources are typically stored in a ResourceDictionary for better organization and scalability. Special theme resources adapt automatically to light or dark modes, ensuring a seamless look across themes.",
+ "relatedControls": [
+ "Style",
+ "Templates",
+ "Binding"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls"
+ ],
+ "curatedKeywords": [
+ "ResourceDictionary",
+ "StaticResource",
+ "ThemeResource",
+ "Resources",
+ "lightweight styling"
+ ],
+ "docs": [
+ {
+ "title": "ResourceDictionary and XAML resource references",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/xaml-resource-dictionary"
+ },
+ {
+ "title": "ResourceDictionary - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.resourcedictionary"
+ },
+ {
+ "title": "XAML theme resources",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/xaml-theme-resources"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "XamlResources",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/XamlResources/XamlResourcesPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/XamlResources/XamlResourcesPage.xaml.cs",
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Binding",
+ "microsoft/WinUI-Gallery#Templates",
+ "microsoft/WinUI-Gallery#XamlStyles"
+ ]
+ },
+ "samples": [
+ {
+ "header": "XamlResources",
+ "xaml": "\u003C!-- App.xaml --\u003E\n\u003CApplication\u003E\n \u003CApplication.Resources\u003E\n \u003C!-- Define an application-wide color resource --\u003E\n \u003CColor x:Key=\u0022PrimaryColor\u0022\u003E#0078D4\u003C/Color\u003E\n \u003C/Application.Resources\u003E\n\u003C/Application\u003E\n\n\u003C!-- YourPage.xaml --\u003E\n\u003CPage\u003E\n \u003CPage.Resources\u003E\n \u003C!-- Define page-level solid color brushes --\u003E\n \u003CSolidColorBrush x:Key=\u0022HighlightBrush\u0022 Color=\u0022#A94DC1\u0022 /\u003E\n \u003CSolidColorBrush x:Key=\u0022FontColor\u0022 Color=\u0022White\u0022 /\u003E\n \u003C/Page.Resources\u003E\n\n \u003C!-- StackPanel using the application-level resource \u0027PrimaryColor\u0027 --\u003E\n \u003CStackPanel Background=\u0022{StaticResource PrimaryColor}\u0022 Padding=\u00228\u0022\u003E\n \u003CTextBlock Text=\u0022Using application-level resources\u0022 Foreground=\u0022White\u0022 FontSize=\u002224\u0022 /\u003E\n\n \u003C!-- StackPanel using the page-level resource \u0027HighlightBrush\u0027 --\u003E\n \u003CStackPanel Background=\u0022{StaticResource HighlightBrush}\u0022 Padding=\u00228\u0022 Margin=\u00228\u0022\u003E\n \u003CTextBlock Text=\u0022Using page-level resources\u0022 Foreground=\u0022{StaticResource FontColor}\u0022 FontSize=\u002218\u0022 /\u003E\n\n \u003C!-- StackPanel with control-level resources defined within its own Resources --\u003E\n \u003CStackPanel Padding=\u00228\u0022 Margin=\u00228\u0022\u003E\n \u003CStackPanel.Resources\u003E\n \u003C!-- Define control-level resources --\u003E\n \u003CColor x:Key=\u0022BackgroundColor\u0022\u003E#E2241A\u003C/Color\u003E\n \u003Cx:String x:Key=\u0022Description\u0022\u003EUsing control-level resources\u003C/x:String\u003E\n \u003C/StackPanel.Resources\u003E\n \u003CGrid Background=\u0022{StaticResource BackgroundColor}\u0022 Padding=\u00228\u0022\u003E\n \u003CTextBlock Text=\u0022{StaticResource Description}\u0022 Foreground=\u0022White\u0022/\u003E\n \u003C/Grid\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n \u003C/StackPanel\u003E\n\u003C/Page\u003E",
+ "code": "// Retrieve application-level resource\nvar primaryColor = (Windows.UI.Color)Application.Current.Resources[\u0022PrimaryColor\u0022];\n\n// Retrieve page-level resource\nvar highlightBrush = (SolidColorBrush)this.Resources[\u0022HighlightBrush\u0022];\n\n// Retrieve control-level resources\nvar headerFontSize = (double)newGrid.Resources[\u0022HeaderFontSize\u0022];\nvar welcomeMessage = (string)newGrid.Resources[\u0022Description\u0022];",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "Xamlresources.txt",
+ "source": "WinUIGallery/Samples/XamlResources/Xamlresources.txt",
+ "name": "XamlResources"
+ }
+ },
+ {
+ "header": "StaticResource versus ThemeResource",
+ "xaml": "\u003CStackPanel\u003E\n \u003CGrid Background=\u0022{StaticResource SolidBackgroundFillColorBaseBrush}\u0022\u003E\n \u003CTextBlock\n Text=\u0022StaticResource uses the value defined when the app starts and does not update when the theme changes.\u0022\n Foreground=\u0022{StaticResource TextFillColorPrimaryBrush}\u0022\n FontSize=\u002216\u0022\n TextWrapping=\u0022Wrap\u0022/\u003E\n \u003C/Grid\u003E\n\n \u003CGrid Background=\u0022{ThemeResource SolidBackgroundFillColorBaseBrush}\u0022\u003E\n \u003CTextBlock\n Text=\u0022ThemeResource adapts automatically to the current theme. If the app switches from Light to Dark, the color defined by ThemeResource changes.\u0022\n Foreground=\u0022{ThemeResource TextFillColorPrimaryBrush}\u0022\n FontSize=\u002216\u0022\n TextWrapping=\u0022Wrap\u0022/\u003E\n \u003C/Grid\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "XamlResourcesStaticresourceVersusThemeresource.txt",
+ "source": "WinUIGallery/Samples/XamlResources/XamlResourcesStaticresourceVersusThemeresource.txt",
+ "name": "Staticresource Versus Themeresource"
+ }
+ },
+ {
+ "header": "Define a new theme resource",
+ "xaml": "\u003CGrid\u003E\n \u003CGrid.Resources\u003E\n \u003CResourceDictionary\u003E\n \u003CResourceDictionary.ThemeDictionaries\u003E\n \u003CResourceDictionary x:Key=\u0022Default\u0022\u003E\n \u003CSolidColorBrush x:Key=\u0022BackgroundBrush\u0022 Color=\u0022#EEE\u0022 /\u003E\n \u003CSolidColorBrush x:Key=\u0022TextBrush\u0022 Color=\u0022#333\u0022 /\u003E\n \u003Cx:String x:Key=\u0022ThemeString\u0022\u003ELight theme\u003C/x:String\u003E\n \u003CImageSource x:Key=\u0022ImageSource\u0022\u003Ems-appx:///Assets/SampleMedia/Light_Image.png\u003C/ImageSource\u003E\n \u003C/ResourceDictionary\u003E\n \u003CResourceDictionary x:Key=\u0022Dark\u0022\u003E\n \u003CSolidColorBrush x:Key=\u0022BackgroundBrush\u0022 Color=\u0022#333\u0022 /\u003E\n \u003CSolidColorBrush x:Key=\u0022TextBrush\u0022 Color=\u0022#EEE\u0022 /\u003E\n \u003Cx:String x:Key=\u0022ThemeString\u0022\u003EDark theme\u003C/x:String\u003E\n \u003CImageSource x:Key=\u0022ImageSource\u0022\u003Ems-appx:///Assets/SampleMedia/Dark_Image.png\u003C/ImageSource\u003E\n \u003C/ResourceDictionary\u003E\n \u003C/ResourceDictionary.ThemeDictionaries\u003E\n \u003C/ResourceDictionary\u003E\n \u003C/Grid.Resources\u003E\n \u003CStackPanel\n MaxWidth=\u0022700\u0022\n Padding=\u00228\u0022\n HorizontalAlignment=\u0022Center\u0022\n VerticalAlignment=\u0022Center\u0022\n Background=\u0022{ThemeResource BackgroundBrush}\u0022\u003E\n \u003CTextBlock\n Foreground=\u0022{ThemeResource TextBrush}\u0022\n Style=\u0022{StaticResource SubtitleTextBlockStyle}\u0022\n Text=\u0022{ThemeResource ThemeString}\u0022 /\u003E\n \u003CImage Source=\u0022{ThemeResource ImageSource}\u0022 /\u003E\n \u003C/StackPanel\u003E\n\u003C/Grid\u003E",
+ "gallery": {
+ "snippet": "XamlResourcesDefineNewThemeResource.txt",
+ "source": "WinUIGallery/Samples/XamlResources/XamlResourcesDefineNewThemeResource.txt",
+ "name": "Define New Theme Resource"
+ }
+ }
+ ]
+ },
+ {
+ "id": "xamlstyles",
+ "name": "Style",
+ "description": "A XAML style is a Reusable property settings to define consistent UI design elements.",
+ "details": "XAML Styles in WinUI 3 are reusable sets of property values that you can apply to multiple controls. They help maintain a consistent look and feel across your app. Instead of setting the same properties on every control, you define a style once and then reuse it wherever needed.",
+ "apiNamespace": "Microsoft.UI.Xaml",
+ "relatedControls": [
+ "Resources",
+ "Templates",
+ "Binding"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject"
+ ],
+ "curatedKeywords": [
+ "Setter",
+ "BasedOn",
+ "implicit style",
+ "default style"
+ ],
+ "docs": [
+ {
+ "title": "Style - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.style"
+ },
+ {
+ "title": "XAML styles",
+ "uri": "https://learn.microsoft.com/windows/apps/design/style/xaml-styles"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "XamlStyles",
+ "group": {
+ "id": "FundamentalsItem",
+ "title": "Fundamentals"
+ },
+ "page": "WinUIGallery/Samples/XamlStyles/XamlStylesPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/XamlStyles/XamlStylesPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject"
+ ],
+ "badges": [
+ "New"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#Binding",
+ "microsoft/WinUI-Gallery#Templates",
+ "microsoft/WinUI-Gallery#XamlResources"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Creating and applying a style",
+ "xaml": "\u003CStackPanel Spacing=\u00228\u0022\u003E\n \u003CStackPanel.Resources\u003E\n \u003CStyle x:Key=\u0022CustomButtonStyle\u0022 TargetType=\u0022Button\u0022 BasedOn=\u0022{StaticResource ButtonRevealStyle}\u0022\u003E\n \u003CSetter Property=\u0022Background\u0022 Value=\u0022{ThemeResource AccentAcrylicBackgroundFillColorDefaultBrush}\u0022 /\u003E\n \u003CSetter Property=\u0022MinWidth\u0022 Value=\u0022200\u0022 /\u003E\n \u003C/Style\u003E\n \u003C/StackPanel.Resources\u003E\n \u003CButton Content=\u0022Default button\u0022 /\u003E\n \u003CButton Content=\u0022Styled button\u0022 Style=\u0022{StaticResource CustomButtonStyle}\u0022 /\u003E\n \u003CButton Content=\u0022Styled button (overridden)\u0022 Style=\u0022{StaticResource CustomButtonStyle}\u0022\n Background=\u0022{ThemeResource SystemFillColorCriticalBackgroundBrush}\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "XamlStylesCreatingApplyingStyle.txt",
+ "source": "WinUIGallery/Samples/XamlStyles/XamlStylesCreatingApplyingStyle.txt",
+ "name": "Creating Applying Style"
+ }
+ },
+ {
+ "header": "Style without a key (implicit style)",
+ "xaml": "\u003CStackPanel\u003E\n \u003CStackPanel.Resources\u003E\n \u003CStyle TargetType=\u0022TextBlock\u0022\u003E\n \u003CSetter Property=\u0022FontSize\u0022 Value=\u002216\u0022 /\u003E\n \u003CSetter Property=\u0022FontFamily\u0022 Value=\u0022Consolas\u0022 /\u003E\n \u003CSetter Property=\u0022FontWeight\u0022 Value=\u0022Bold\u0022 /\u003E\n \u003C/Style\u003E\n \u003C/StackPanel.Resources\u003E\n\n \u003CTextBlock Text=\u0022This style is applied automatically!\u0022 /\u003E\n \u003CTextBlock Text=\u0022No need to set a key.\u0022 /\u003E\n\u003C/StackPanel\u003E",
+ "gallery": {
+ "snippet": "XamlStylesStyleWithoutKeyImplicit.txt",
+ "source": "WinUIGallery/Samples/XamlStyles/XamlStylesStyleWithoutKeyImplicit.txt",
+ "name": "Style Without Key Implicit"
+ }
+ }
+ ]
+ },
+ {
+ "id": "xamluicommand",
+ "name": "XamlUICommand",
+ "description": "An object which is used to define the look and feel of a given command.",
+ "details": "An object which is used to define the look and feel of a given command, which can be reused across your app, and which is understood natively by the standard XAML controls.",
+ "apiNamespace": "Microsoft.UI.Xaml.Input",
+ "relatedControls": [
+ "StandardUICommand",
+ "AppBarButton",
+ "AppBarToggleButton",
+ "CommandBar"
+ ],
+ "usings": [
+ "Microsoft.UI.Xaml.Controls",
+ "Microsoft.UI.Xaml.Input"
+ ],
+ "keywords": [
+ "Object",
+ "DependencyObject"
+ ],
+ "docs": [
+ {
+ "title": "Guidelines",
+ "uri": "https://learn.microsoft.com/windows/apps/design/controls/commanding#command-experiences-using-the-xamluicommand-class"
+ },
+ {
+ "title": "XamlUICommand - API",
+ "uri": "https://learn.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.input.xamluicommand"
+ }
+ ],
+ "gallery": {
+ "uniqueId": "XamlUICommand",
+ "group": {
+ "id": "MenusAndToolbars",
+ "title": "Menus \u0026 toolbars"
+ },
+ "page": "WinUIGallery/Samples/XamlUICommand/XamlUICommandPage.xaml",
+ "codeBehind": "WinUIGallery/Samples/XamlUICommand/XamlUICommandPage.xaml.cs",
+ "baseClasses": [
+ "Object",
+ "DependencyObject"
+ ],
+ "relatedSamples": [
+ "microsoft/WinUI-Gallery#AppBarButton",
+ "microsoft/WinUI-Gallery#AppBarToggleButton",
+ "microsoft/WinUI-Gallery#CommandBar",
+ "microsoft/WinUI-Gallery#StandardUICommand"
+ ]
+ },
+ "samples": [
+ {
+ "header": "Creating a reusable command with XamlUICommand",
+ "xaml": "\u003CPage.Resources\u003E\n \u003CXamlUICommand x:Name=\u0022CustomXamlUICommand\u0022 ExecuteRequested=\u0022CustomXamlUICommand_ExecuteRequested\u0022 \n\tDescription=\u0022This is a custom command\u0022 Label=\u0022Custom Command\u0022\u003E\n \u003CXamlUICommand.IconSource\u003E\n \u003CSymbolIconSource Symbol=\u0022Favorite\u0022 /\u003E\n \u003C/XamlUICommand.IconSource\u003E\n \u003CXamlUICommand.KeyboardAccelerators\u003E\n \u003CKeyboardAccelerator Key=\u0022D\u0022 Modifiers=\u0022Control\u0022/\u003E\n \u003C/XamlUICommand.KeyboardAccelerators\u003E\n \u003C/XamlUICommand\u003E\n\u003C/Page.Resources\u003E\n\n\u003CRelativePanel Grid.Row=\u00221\u0022\u003E\n \u003CAppBarButton x:Name=\u0022CustomButton\u0022 Command=\u0022{StaticResource CustomXamlUICommand}\u0022/\u003E\n \u003CTextBlock x:Name=\u0022XamlUICommandOutput\u0022 Margin=\u00228,0,0,0\u0022 FontFamily=\u0022Global User Interface\u0022 \n RelativePanel.RightOf=\u0022CustomButton\u0022 RelativePanel.AlignVerticalCenterWith=\u0022CustomButton\u0022 /\u003E\n\u003C/RelativePanel\u003E",
+ "code": "private void CustomXamlUICommand_ExecuteRequested(XamlUICommand sender, ExecuteRequestedEventArgs args)\n{\n XamlUICommandOutput.Text = \u0022You fired the custom command\u0022;\n}",
+ "language": "csharp",
+ "gallery": {
+ "snippet": "CreatingReusableCommandXamluicommand.txt",
+ "source": "WinUIGallery/Samples/XamlUICommand/CreatingReusableCommandXamluicommand.txt",
+ "name": "Creating Reusable Command Xamluicommand"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/CatalogGeneratorTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/CatalogGeneratorTests.cs
new file mode 100644
index 000000000..ecb1213d7
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/CatalogGeneratorTests.cs
@@ -0,0 +1,510 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Exercises CatalogGenerator against small, synthetic ControlInfoData.json + Samples/ fixtures
+/// (never the real repository data) so each rule can be tested in isolation.
+///
+[TestClass]
+public sealed class CatalogGeneratorTests
+{
+ private string _fixtureRoot = string.Empty;
+
+ [TestInitialize]
+ public void CreateFixtureRoot()
+ {
+ _fixtureRoot = Path.Combine(Path.GetTempPath(), "CatalogExporterTests_" + Guid.NewGuid().ToString("N"));
+ Directory.CreateDirectory(_fixtureRoot);
+ File.WriteAllText(Path.Combine(_fixtureRoot, "WinUIGallery.slnx"), "");
+ }
+
+ [TestCleanup]
+ public void DeleteFixtureRoot()
+ {
+ if (Directory.Exists(_fixtureRoot))
+ {
+ Directory.Delete(_fixtureRoot, recursive: true);
+ }
+ }
+
+ private CatalogGenerationOptions Options() => new() { RepoRoot = _fixtureRoot };
+
+ /// Builds a SampleDefinition bundle in the real "--- section" format.
+ private static string Bundle(string? header = null, string? xaml = null, string? csharp = null)
+ {
+ List parts = [];
+ if (header is not null)
+ {
+ parts.Add("--- header\n" + header);
+ }
+
+ if (xaml is not null)
+ {
+ parts.Add("--- xaml\n" + xaml);
+ }
+
+ if (csharp is not null)
+ {
+ parts.Add("--- c#\n" + csharp);
+ }
+
+ return string.Join('\n', parts) + "\n";
+ }
+
+ private void WriteControlInfoData(string json)
+ {
+ string dir = Path.Combine(_fixtureRoot, "WinUIGallery", "SampleSupport", "Data");
+ Directory.CreateDirectory(dir);
+ File.WriteAllText(Path.Combine(dir, "ControlInfoData.json"), json);
+ }
+
+ ///
+ /// Wraps fixture markup in a page that declares the namespaces every real sample page uses.
+ /// The exporter parses pages as XML, so a fragment using the controls: prefix without
+ /// declaring it would fail to load for a reason unrelated to what the test is checking.
+ ///
+ private static string Page(string inner) =>
+ $"""
+ {inner}
+ """;
+
+ private void WriteSample(string uniqueId, string pageXamlBody, params (string FileName, string Contents)[] extraFiles)
+ {
+ string folder = Path.Combine(_fixtureRoot, "WinUIGallery", "Samples", uniqueId);
+ Directory.CreateDirectory(folder);
+ File.WriteAllText(Path.Combine(folder, uniqueId + "Page.xaml"), pageXamlBody);
+ File.WriteAllText(Path.Combine(folder, uniqueId + "Page.xaml.cs"), "// code-behind");
+ foreach ((string fileName, string contents) in extraFiles)
+ {
+ File.WriteAllText(Path.Combine(folder, fileName), contents);
+ }
+ }
+
+ private static string TwoItemDocument(string extraForFirstItem = "") => $$"""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [
+ {
+ "UniqueId": "SampleOne",
+ "Title": "Sample One",
+ "Subtitle": "First sample",
+ "Tags": [ "alpha" ],
+ "RelatedControls": [ "SampleTwo" ]
+ {{extraForFirstItem}}
+ },
+ {
+ "UniqueId": "SampleTwo",
+ "Title": "Sample Two"
+ }
+ ]
+ }
+ ]
+ }
+ """;
+
+ [TestMethod]
+ public void Generate_ProducesExpectedFieldsAndOmitsEmptyOptionalFields()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""), ("SampleOneBasic.txt", Bundle("A basic button.", "")));
+ WriteSample("SampleTwo", "");
+
+ SampleIndex index = CatalogGenerator.Generate(Options()).Index;
+
+ Assert.AreEqual(2, index.ControlCount);
+ Assert.AreEqual(2, index.Controls.Count);
+
+ IndexControl one = index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+ Assert.AreEqual("sampleone", one.Id);
+ Assert.AreEqual("Sample One", one.Name);
+ Assert.AreEqual("First sample", one.Description);
+ CollectionAssert.AreEqual(new[] { "alpha" }, one.CuratedKeywords);
+ CollectionAssert.AreEqual(new[] { "microsoft/WinUI-Gallery#SampleTwo" }, one.Gallery.RelatedSamples);
+ Assert.AreEqual(1, one.Samples.Count);
+ Assert.AreEqual("SampleOneBasic.txt", one.Samples[0].Gallery.Snippet);
+ Assert.AreEqual("Basic", one.Samples[0].Gallery.Name);
+ Assert.AreEqual("A basic button.", one.Samples[0].Header);
+ Assert.AreEqual("", one.Samples[0].Xaml);
+
+ IndexControl two = index.Controls.Single(c => c.Gallery.UniqueId == "SampleTwo");
+ Assert.IsNull(two.Description, "Optional fields with no source data must be omitted (null), not empty strings.");
+ Assert.IsNull(two.CuratedKeywords);
+ Assert.IsNull(two.Gallery.RelatedSamples);
+ Assert.AreEqual(0, two.Samples.Count);
+ }
+
+ [TestMethod]
+ public void Generate_SortsControlsById()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [
+ { "UniqueId": "Zebra", "Title": "Zebra" },
+ { "UniqueId": "Apple", "Title": "Apple" }
+ ]
+ }
+ ]
+ }
+ """);
+ WriteSample("Zebra", "");
+ WriteSample("Apple", "");
+
+ SampleIndex index = CatalogGenerator.Generate(Options()).Index;
+
+ CollectionAssert.AreEqual(
+ new[] { "apple", "zebra" },
+ index.Controls.Select(c => c.Id).ToArray());
+ }
+
+ [TestMethod]
+ public void Serialize_IsDeterministicAcrossRuns()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", "");
+ WriteSample("SampleTwo", "");
+
+ string first = CatalogGenerator.Serialize(CatalogGenerator.Generate(Options()).Index);
+ string second = CatalogGenerator.Serialize(CatalogGenerator.Generate(Options()).Index);
+
+ Assert.AreEqual(first, second);
+ StringAssert.EndsWith(first, "\n");
+ Assert.IsFalse(first.Contains('\r'), "Serialized index must use LF line endings only.");
+ }
+
+ [TestMethod]
+ public void Generate_ThrowsOnDuplicateUniqueId()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [
+ { "UniqueId": "Dup", "Title": "First" },
+ { "UniqueId": "Dup", "Title": "Second" }
+ ]
+ }
+ ]
+ }
+ """);
+ WriteSample("Dup", "");
+
+ CatalogValidationException ex = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ Assert.IsTrue(ex.Issues.Any(i => i.Message.Contains("Duplicate", StringComparison.Ordinal)));
+ }
+
+ [TestMethod]
+ public void Generate_ThrowsWhenSampleFolderIsMissing()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [ { "UniqueId": "Ghost", "Title": "Ghost" } ]
+ }
+ ]
+ }
+ """);
+ // Intentionally do not create a WinUIGallery/Samples/Ghost folder.
+
+ CatalogValidationException ex = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ Assert.IsTrue(ex.Issues.Any(i => i.UniqueId == "Ghost" && i.Message.Contains("No sample folder", StringComparison.Ordinal)));
+ }
+
+ [TestMethod]
+ public void Generate_ThrowsWhenPageFileCaseDoesNotMatch()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [ { "UniqueId": "Casey", "Title": "Casey" } ]
+ }
+ ]
+ }
+ """);
+ string folder = Path.Combine(_fixtureRoot, "WinUIGallery", "Samples", "Casey");
+ Directory.CreateDirectory(folder);
+ // Wrong case: "caseyPage.xaml" instead of the expected "CaseyPage.xaml".
+ File.WriteAllText(Path.Combine(folder, "caseyPage.xaml"), "");
+
+ CatalogValidationException ex = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ Assert.IsTrue(ex.Issues.Any(i => i.UniqueId == "Casey" && i.Message.Contains("case-exact", StringComparison.Ordinal)));
+ }
+
+ [TestMethod]
+ public void Generate_ThrowsOnBrokenRelatedControlsReference()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [
+ { "UniqueId": "Lonely", "Title": "Lonely", "RelatedControls": [ "DoesNotExist" ] }
+ ]
+ }
+ ]
+ }
+ """);
+ WriteSample("Lonely", "");
+
+ CatalogValidationException ex = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ Assert.IsTrue(ex.Issues.Any(i => i.Message.Contains("does not resolve", StringComparison.Ordinal)));
+ }
+
+ [TestMethod]
+ public void Generate_ThrowsWhenSampleDefinitionSnippetIsMissing()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [ { "UniqueId": "Snippety", "Title": "Snippety" } ]
+ }
+ ]
+ }
+ """);
+ WriteSample("Snippety", Page(""""""));
+
+ CatalogValidationException ex = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ Assert.IsTrue(ex.Issues.Any(i => i.UniqueId == "Snippety" && i.Message.Contains("SampleDefinition", StringComparison.Ordinal)));
+ }
+
+ [TestMethod]
+ public void Generate_ExcludesItemsMarkedCatalogExclude()
+ {
+ WriteControlInfoData("""
+ {
+ "Groups": [
+ {
+ "UniqueId": "GroupA",
+ "Title": "Group A",
+ "Items": [
+ { "UniqueId": "Hidden", "Title": "Hidden", "Catalog": { "Exclude": true } },
+ { "UniqueId": "Visible", "Title": "Visible" }
+ ]
+ }
+ ]
+ }
+ """);
+ // "Hidden" has no on-disk folder at all: Exclude must short-circuit before folder validation.
+ WriteSample("Visible", "");
+
+ SampleIndex index = CatalogGenerator.Generate(Options()).Index;
+
+ Assert.AreEqual(1, index.ControlCount);
+ Assert.AreEqual("Visible", index.Controls.Single().Gallery.UniqueId);
+ }
+
+ [TestMethod]
+ public void Generate_MergesCatalogAliasesIntoCuratedKeywordsAndKeepsRelatedSamples()
+ {
+ WriteControlInfoData(TwoItemDocument("""
+ ,
+ "Catalog": {
+ "Aliases": [ "shortcut" ],
+ "RelatedSamples": [ "other/repo#thing" ]
+ }
+ """));
+ WriteSample("SampleOne", "");
+ WriteSample("SampleTwo", "");
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ // Tags and aliases are both author-written, and the contract has a single slot for those.
+ CollectionAssert.AreEqual(new[] { "alpha", "shortcut" }, one.CuratedKeywords);
+ CollectionAssert.AreEqual(
+ new[] { "microsoft/WinUI-Gallery#SampleTwo", "other/repo#thing" },
+ one.Gallery.RelatedSamples);
+ }
+
+ ///
+ /// ControlInfoData.json stores UniqueIds in RelatedControls, but the contract's field is
+ /// display names and consumers render it verbatim. "SampleTwo" is titled "Sample Two", so a
+ /// straight copy would surface an internal id to a reader.
+ ///
+ [TestMethod]
+ public void Generate_ResolvesRelatedControlsToDisplayNames()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", "");
+ WriteSample("SampleTwo", "");
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ CollectionAssert.AreEqual(new[] { "Sample Two" }, one.RelatedControls);
+ // The source-qualified id keeps living in the gallery extension, where ids belong.
+ CollectionAssert.AreEqual(new[] { "microsoft/WinUI-Gallery#SampleTwo" }, one.Gallery.RelatedSamples);
+ }
+
+ ///
+ /// The contract's "usings" exists so a consumer can make a snippet compile standalone. They
+ /// come from the imports the page's code-behind was written against, minus the gallery's own
+ /// namespaces — prepending "using WinUIGallery.Helpers;" would break the very build this
+ /// field exists to fix.
+ ///
+ [TestMethod]
+ public void Generate_CollectsUsingsFromCodeBehindAndExcludesGalleryNamespaces()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", csharp: "var items = new ObservableCollection();")));
+ WriteSample("SampleTwo", "");
+
+ File.WriteAllText(
+ Path.Combine(_fixtureRoot, "WinUIGallery", "Samples", "SampleOne", "SampleOnePage.xaml.cs"),
+ """
+ using System;
+ using System.Collections.ObjectModel;
+ using static System.Math;
+ using Alias = System.Text.StringBuilder;
+ using WinUIGallery.Helpers;
+ """);
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ // Static and alias forms are dropped: the consumer re-emits each entry as "using X;".
+ CollectionAssert.AreEqual(new[] { "System", "System.Collections.ObjectModel" }, one.Usings);
+ }
+
+ /// A control with no C# has nothing for a consumer to prepend.
+ [TestMethod]
+ public void Generate_OmitsUsingsWhenControlHasNoCode()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", xaml: "")));
+ WriteSample("SampleTwo", "");
+
+ File.WriteAllText(
+ Path.Combine(_fixtureRoot, "WinUIGallery", "Samples", "SampleOne", "SampleOnePage.xaml.cs"),
+ "using System;");
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ Assert.IsNull(one.Usings);
+ }
+
+ ///
+ /// A prefixed attribute must not hide a prefixed type in its own value. In
+ /// x:DataType="local:Contact" the "local" import is the one a reader actually needs, and it
+ /// was being missed because the scan consumed the "=" while matching the attribute name.
+ ///
+ [TestMethod]
+ public void Generate_DetectsPrefixInValueOfPrefixedAttribute()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample(
+ "SampleOne",
+ """
+
+
+
+ """,
+ ("Snippet.txt", Bundle(header: "One", xaml: """""")));
+ WriteSample("SampleTwo", "");
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ CollectionAssert.Contains(
+ one.XmlnsImports ?? one.Samples.Single().XmlnsImports,
+ "xmlns:local=\"using:WinUIGallery.ControlPages\"");
+ }
+
+ ///
+ /// ControlExample loads a bundle as "Samples/<SampleDefinition>", so the directory half of
+ /// the value has to name the sample's own folder. Validating only the file name would let a
+ /// wrong-folder typo through here and leave it to appear as an empty code viewer at runtime.
+ ///
+ [TestMethod]
+ public void Generate_RejectsSampleDefinitionNamingTheWrongFolder()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", xaml: "")));
+ WriteSample("SampleTwo", "");
+
+ CatalogValidationException error = Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+
+ StringAssert.Contains(error.Message, "WrongFolder\\Snippet.txt");
+ }
+
+ ///
+ /// A bare file name is rejected for the same reason: the gallery would resolve it as
+ /// "Samples/Snippet.txt" and find nothing there.
+ ///
+ [TestMethod]
+ public void Generate_RejectsSampleDefinitionWithNoFolder()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", xaml: "")));
+ WriteSample("SampleTwo", "");
+
+ Assert.ThrowsException(() => CatalogGenerator.Generate(Options()));
+ }
+
+ ///
+ /// A snippet that declares a prefix on its own root needs nothing from the page, so it is
+ /// published rather than treated as unresolvable.
+ ///
+ [TestMethod]
+ public void Generate_KeepsXamlWhoseFragmentDeclaresItsOwnPrefix()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", xaml: """Hi""")));
+ WriteSample("SampleTwo", "");
+
+ IndexControl one = CatalogGenerator.Generate(Options()).Index.Controls.Single(c => c.Gallery.UniqueId == "SampleOne");
+
+ Assert.IsNotNull(one.Samples.Single().Xaml);
+ Assert.IsNull(one.Samples.Single().Gallery.XamlOmittedUnboundPrefixes);
+ }
+
+ ///
+ /// A prefix neither the page nor the fragment declares cannot be published as an import, so the
+ /// XAML is omitted rather than shipped in a state that will not compile on arrival.
+ ///
+ [TestMethod]
+ public void Generate_OmitsXamlBindingAPrefixNothingDeclares()
+ {
+ WriteControlInfoData(TwoItemDocument());
+ WriteSample("SampleOne", Page(""""""),
+ ("Snippet.txt", Bundle(header: "One", xaml: "", csharp: "int x = 1;")));
+ WriteSample("SampleTwo", "");
+
+ IndexSample sample = CatalogGenerator.Generate(Options()).Index.Controls
+ .Single(c => c.Gallery.UniqueId == "SampleOne").Samples.Single();
+
+ Assert.IsNull(sample.Xaml);
+ CollectionAssert.AreEqual(new[] { "mystery" }, sample.Gallery.XamlOmittedUnboundPrefixes);
+ Assert.IsNotNull(sample.Code);
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/ContractConformanceTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/ContractConformanceTests.cs
new file mode 100644
index 000000000..80317ea1b
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/ContractConformanceTests.cs
@@ -0,0 +1,169 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Keeps the generated index conformant with the shared contract published by microsoft/winappCli
+/// at docs/winui-sample-index.schema.json.
+///
+/// The contract is owned by another repository, so there is no schema file here to diff against.
+/// What these tests protect instead is the part a consumer actually depends on: that the field
+/// names we emit are the contract's field names, and that the guarantees its reader relies on
+/// hold. A typo such as "xmlnsImport" would still produce valid JSON and a passing up-to-date
+/// test, and would simply arrive as nothing on the other side.
+///
+[TestClass]
+public sealed class ContractConformanceTests
+{
+ private static string RepoRoot => CatalogGenerator.FindRepoRoot(AppContext.BaseDirectory);
+
+ ///
+ /// Every property name the contract defines, transcribed from
+ /// docs/winui-sample-index.schema.json. Extras are allowed by the schema
+ /// ("additionalProperties": true), which is why the gallery-specific fields below are listed
+ /// separately rather than folded in.
+ ///
+ private static readonly string[] ContractDocumentProperties =
+ ["schemaVersion", "source", "generatedAtUtc", "controls"];
+
+ private static readonly string[] ContractControlProperties =
+ [
+ "id", "name", "description", "details", "apiNamespace", "nugetPackage",
+ "relatedControls", "xmlnsImports", "usings", "keywords", "curatedKeywords", "docs", "samples",
+ ];
+
+ private static readonly string[] ContractSampleProperties =
+ ["header", "xaml", "code", "language", "details", "xmlnsImports"];
+
+ private static readonly string[] ContractDocLinkProperties = ["title", "uri"];
+
+ ///
+ /// Fields this repository adds on top of the contract. They are grouped under "gallery" (plus
+ /// the document-level provenance) precisely so that this list stays short and a new field
+ /// cannot be mistaken for part of the shared contract.
+ ///
+ private static readonly string[] GalleryDocumentExtras = ["$schema", "generator", "controlCount"];
+
+ private static readonly string[] GalleryObjectExtras = ["gallery"];
+
+ /// The property names the writer will emit for a type.
+ private static string[] SerializedNames(Type type) => type
+ .GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Select(p => p.GetCustomAttribute()?.Name
+ ?? CatalogGenerator.WriteOptions.PropertyNamingPolicy!.ConvertName(p.Name))
+ .ToArray();
+
+ private static void AssertOnlyKnownProperties(Type type, string[] contract, string[] extras, string what)
+ {
+ string[] allowed = [.. contract, .. extras];
+ string[] unknown = SerializedNames(type)
+ .Where(n => !allowed.Contains(n, StringComparer.Ordinal))
+ .OrderBy(n => n, StringComparer.Ordinal)
+ .ToArray();
+
+ Assert.AreEqual(
+ 0,
+ unknown.Length,
+ $"{what} emits {string.Join(", ", unknown)}, which the shared contract does not define. "
+ + "A consumer ignores unknown fields, so this would be published and silently dropped. "
+ + "Either use the contract's name, or add it under the 'gallery' object with the others.");
+ }
+
+ [TestMethod]
+ public void EmittedPropertyNames_AreTheContractsNames()
+ {
+ AssertOnlyKnownProperties(typeof(SampleIndex), ContractDocumentProperties, GalleryDocumentExtras, "The index root");
+ AssertOnlyKnownProperties(typeof(IndexControl), ContractControlProperties, GalleryObjectExtras, "A control");
+ AssertOnlyKnownProperties(typeof(IndexSample), ContractSampleProperties, GalleryObjectExtras, "A sample");
+ AssertOnlyKnownProperties(typeof(IndexDocLink), ContractDocLinkProperties, [], "A docs entry");
+ }
+
+ [TestMethod]
+ public void RequiredContractFields_ArePresentOnEveryEntry()
+ {
+ // The schema requires schemaVersion and controls at the document level, and id and samples
+ // on each control. Everything else is optional, so these are the only fields whose absence
+ // makes the file unreadable rather than merely sparse.
+ SampleIndex index = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot }).Index;
+
+ Assert.AreEqual(1, index.SchemaVersion, "version 1 is the only value the contract accepts");
+ Assert.AreEqual("gallery", index.Source, "the consumer keys its source-specific behaviour off this value");
+ Assert.IsTrue(index.Controls.Count > 0);
+
+ foreach (IndexControl control in index.Controls)
+ {
+ Assert.IsFalse(string.IsNullOrWhiteSpace(control.Id), $"{control.Gallery.UniqueId} has no id");
+ Assert.IsNotNull(control.Samples, $"{control.Id} must declare a samples array, even when empty");
+ }
+ }
+
+ [TestMethod]
+ public void ControlIds_AreUniqueAndUrlSafe()
+ {
+ // The consumer derives its own sample ids as "{control id}-{n}", so these end up in user-
+ // visible identifiers. A duplicate would merge two gallery pages into one.
+ SampleIndex index = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot }).Index;
+
+ string[] duplicates = index.Controls
+ .GroupBy(c => c.Id, StringComparer.Ordinal)
+ .Where(g => g.Count() > 1)
+ .Select(g => g.Key)
+ .ToArray();
+
+ Assert.AreEqual(0, duplicates.Length, "Duplicate control ids: " + string.Join(", ", duplicates));
+
+ string[] unsafeIds = index.Controls
+ .Where(c => !c.Id.All(ch => char.IsAsciiLetterOrDigit(ch) || ch is '-' or '_'))
+ .Select(c => c.Id)
+ .ToArray();
+
+ Assert.AreEqual(0, unsafeIds.Length, "Control ids must be URL-safe: " + string.Join(", ", unsafeIds));
+ }
+
+ [TestMethod]
+ public void EveryPublishedXamlFragment_SurvivesTheConsumersParser()
+ {
+ // This is the guarantee the whole export depends on. The consumer parses each fragment and
+ // discards whatever fails, without reporting it, so anything that slips through here is a
+ // sample that appears to ship and never arrives.
+ SampleIndex index = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot }).Index;
+
+ string[] malformed = index.Controls
+ .SelectMany(c => c.Samples.Select(s => (Control: c, Sample: s)))
+ .Where(x => x.Sample.Xaml is not null && !XamlFragment.IsWellFormed(x.Sample.Xaml))
+ .Select(x => $"{x.Control.Id}/{x.Sample.Gallery.Snippet}")
+ .ToArray();
+
+ Assert.AreEqual(0, malformed.Length, "These published fragments would be silently dropped: " + string.Join(", ", malformed));
+ }
+
+ [TestMethod]
+ public void SchemaUrl_PointsAtThePublishedContract()
+ {
+ // The file is self-describing: a reader who finds it should be able to reach the contract
+ // that defines it without knowing this repository's history.
+ Assert.AreEqual(
+ "https://raw.githubusercontent.com/microsoft/winappCli/main/docs/winui-sample-index.schema.json",
+ new SampleIndex().Schema);
+ }
+
+ [TestMethod]
+ public void Index_DoesNotEmbedAGenerationTimestamp()
+ {
+ // The contract offers generatedAtUtc, but the file is committed and a CI check regenerates
+ // it to prove it is current. A timestamp would make every regeneration differ and turn
+ // that check into noise, so it is deliberately not emitted.
+ string json = CatalogGenerator.Serialize(new SampleIndex());
+
+ Assert.IsFalse(
+ JsonDocument.Parse(json).RootElement.TryGetProperty("generatedAtUtc", out _),
+ "a generation timestamp would make the committed file differ on every run");
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/ManifestUpToDateTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/ManifestUpToDateTests.cs
new file mode 100644
index 000000000..a18f8d157
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/ManifestUpToDateTests.cs
@@ -0,0 +1,305 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text.RegularExpressions;
+using System.Xml.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Guards against a stale committed index: regenerates it from the real, current repository data
+/// and fails if it does not byte-for-byte match what is checked in. Run
+/// `dotnet run --project tools/CatalogExporter -- generate` and commit the result if this test
+/// fails.
+///
+[TestClass]
+public sealed class ManifestUpToDateTests
+{
+ private static string RepoRoot => CatalogGenerator.FindRepoRoot(AppContext.BaseDirectory);
+
+ [TestMethod]
+ public void CommittedManifest_MatchesFreshGeneration()
+ {
+ string repoRoot = RepoRoot;
+ string manifestPath = Path.Combine(repoRoot, "catalog", "windows-samples.json");
+
+ Assert.IsTrue(File.Exists(manifestPath), $"{manifestPath} is missing. Run 'dotnet run --project tools/CatalogExporter -- generate' and commit the result.");
+
+ string committed = File.ReadAllText(manifestPath).Replace("\r\n", "\n");
+ string fresh = CatalogGenerator.Serialize(CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = repoRoot }).Index);
+
+ Assert.AreEqual(
+ fresh,
+ committed,
+ "catalog/windows-samples.json is stale relative to ControlInfoData.json / the Samples folders. Run 'dotnet run --project tools/CatalogExporter -- generate' and commit the result.");
+ }
+
+ [TestMethod]
+ public void RealRepository_SnippetsWithUnpublishableXamlAreTheKnownSet()
+ {
+ // These snippets are written for the gallery's own code viewer, where a human reads
+ // "" as "your existing window". That is not a well-formed XML fragment, so a
+ // consumer of the index parses it, fails, and discards it silently. The exporter omits the
+ // XAML instead and records a warning; every one of these samples still publishes its C#.
+ //
+ // The set is pinned so that a newly broken snippet shows up as a failure here rather than
+ // quietly disappearing from the index. If you make one of these paste-ready, delete its
+ // line. Growing the list should be a deliberate choice, not a default.
+ //
+ // OtherXamlEasingFunctions.txt is the one entry that is not an elision: it uses a token as
+ // an element name, <$(EasingFunction)/>, whose value comes from a ComboBox populated in
+ // code-behind. Nothing in the markup can resolve it, so it cannot be published as XAML.
+ //
+ // The ItemsRepeater, NavigationView, TreeView, FlipView and ConnectedAnimation entries fail
+ // for a different reason: they bind a prefix ("local:", "common:", "l:", "data:") that
+ // their page never declares, so no import can be published for it. Well-formedness cannot
+ // catch that - this exporter and the consumer both synthesize a declaration for every
+ // prefix they see - so the fragment would parse on both sides and break only once a reader
+ // pasted it with the imports we published. These prefixes name gallery-internal types, so
+ // there is no import that would make them portable; omitting is the only honest option.
+ //
+ // FlipviewShowingBoundData.txt and LayingOutNestedItemsrepeaters.txt carry no C#, so they
+ // leave the index entirely rather than merely losing their XAML. That is a real cost, and
+ // accepted: both were only ever publishable as markup a consumer could not compile.
+ string[] expected =
+ [
+ "AppWindow: 'AppWindowSettingMinimumMaximumWidth.txt'",
+ "AppWindow: 'AppwindowCompactoverlaypresenter.txt'",
+ "AppWindow: 'AppwindowFullscreenpresenter.txt'",
+ "AppWindow: 'AppwindowOverlapedpresenter.txt'",
+ "AppWindow: 'CenteringAppwindowScreenAvailable.txt'",
+ "AppWindow: 'CreatingCustomizingAppwindowWindow.txt'",
+ "AppWindow: 'ModalWindowOverlappedpresenterAppwindow.txt'",
+ "Binding: 'ConverterBinding.txt'",
+ "ConnectedAnimation: 'ConnectedAnimationItemsrepeater.txt'",
+ "ConnectedAnimation: 'ConnectedAnimationListPage.txt'",
+ "CustomUserControls: 'CustomUserControlsBasicCustomPasswordBox.txt'",
+ "CustomUserControls: 'CustomUserControlsCounterControlIncrementDecrement.txt'",
+ "CustomUserControls: 'CustomUserControlsTemperatureConverterUsercontrolExample.txt'",
+ "EasingFunction: 'OtherXamlEasingFunctions.txt'",
+ "FlipView: 'FlipviewShowingBoundData.txt'",
+ "ItemsRepeater: 'ItemsRepeaterVirtualizedContentHeavyLayout.txt'",
+ "ItemsRepeater: 'LayingOutNestedItemsrepeaters.txt'",
+ "NavigationView: 'NavigationViewDataBinding.txt'",
+ "TreeView: 'TreeviewDatabindingItemsource.txt'",
+ "TreeView: 'TreeviewItemtemplateselector.txt'",
+ ];
+
+ CatalogGenerationResult result = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot });
+
+ string[] actual = result.Warnings
+ .Where(w => w.Message.Contains("was omitted", StringComparison.Ordinal))
+ .Select(w => $"{w.UniqueId}: '{w.Message.Split('\'')[1]}'")
+ .OrderBy(w => w, StringComparer.Ordinal)
+ .ToArray();
+
+ CollectionAssert.AreEqual(
+ expected,
+ actual,
+ "The set of snippets whose XAML cannot be published changed. Each omitted snippet is a sample a "
+ + "consumer cannot paste, so confirm the change is intentional before updating this list.");
+ }
+
+ ///
+ /// The index's central promise: every fragment it publishes can be pasted as-is.
+ ///
+ /// This is asserted as a property rather than pinned as a list on purpose. A new sample that
+ /// introduces an unresolvable $(Token) needs no test update — the fallback drops the attribute
+ /// carrying it and this test keeps passing — but any change that let a placeholder reach the
+ /// index fails here, whichever control it came from.
+ ///
+ [TestMethod]
+ public void RealRepository_NoPublishedXamlContainsAPlaceholder()
+ {
+ CatalogGenerationResult result = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot });
+
+ List offenders =
+ [
+ .. from control in result.Index.Controls
+ from sample in control.Samples
+ where TokenFallback.ContainsToken(sample.Xaml)
+ select $"{control.Id}/{sample.Gallery.Snippet}: {string.Join(", ", TokenFallback.TokenNames(sample.Xaml!))}"
+ ];
+
+ Assert.AreEqual(
+ 0,
+ offenders.Count,
+ "Published XAML must never contain a $(Token). Offending samples:\n" + string.Join('\n', offenders));
+ }
+
+ ///
+ /// Dropping the attribute that carried a placeholder must degrade a sample, never delete it. A
+ /// removal that emptied a fragment would cost the sample its XAML, which is the outcome the
+ /// fallback exists to avoid.
+ ///
+ [TestMethod]
+ public void RealRepository_SamplesWithDroppedPlaceholders_StillPublishTheirXaml()
+ {
+ CatalogGenerationResult result = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot });
+
+ List withDrops =
+ [
+ .. from control in result.Index.Controls
+ from sample in control.Samples
+ where sample.Gallery.XamlPlaceholdersDropped is { Count: > 0 }
+ select sample
+ ];
+
+ Assert.IsTrue(withDrops.Count > 0, "Expected at least one sample to exercise the placeholder fallback.");
+
+ foreach (IndexSample sample in withDrops)
+ {
+ Assert.IsNotNull(sample.Xaml, $"'{sample.Gallery.Snippet}' lost its XAML entirely to placeholder removal.");
+ Assert.IsTrue(
+ XamlFragment.IsWellFormed(sample.Xaml!),
+ $"'{sample.Gallery.Snippet}' stopped parsing after placeholder removal.");
+ }
+ }
+
+ ///
+ /// The published import list has to be complete, not merely correct. A consumer pastes exactly
+ /// the imports this index gives it, so a fragment binding a prefix that is missing from them
+ /// does not compile on arrival — and neither parser catches it, because both synthesize a
+ /// declaration for every prefix they encounter.
+ ///
+ /// Asserted as a property rather than pinned as a list, so a new snippet that reaches for an
+ /// undeclared prefix fails here whichever control it came from.
+ ///
+ [TestMethod]
+ public void RealRepository_EveryPublishedFragmentDeclaresThePrefixesItUses()
+ {
+ static Dictionary DeclaredPrefixes(IEnumerable? imports)
+ {
+ Dictionary declarations = new(StringComparer.Ordinal);
+ foreach (string import in imports ?? [])
+ {
+ Match match = Regex.Match(import, @"^xmlns:([A-Za-z_][\w.\-]*)\s*=\s*""([^""]*)""$");
+ if (match.Success)
+ {
+ declarations[match.Groups[1].Value] = match.Groups[2].Value;
+ }
+ }
+
+ return declarations;
+ }
+
+ CatalogGenerationResult result = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot });
+
+ List offenders = [];
+
+ foreach (IndexControl control in result.Index.Controls)
+ {
+ foreach (IndexSample sample in control.Samples)
+ {
+ if (sample.Xaml is null)
+ {
+ continue;
+ }
+
+ // The contract lets a sample override the control's imports wholesale, so the
+ // fallback is either/or rather than a union.
+ Dictionary declared = DeclaredPrefixes(sample.XmlnsImports ?? control.XmlnsImports);
+ List unbound = XamlFragment.UnresolvedPrefixes(sample.Xaml, declared);
+
+ if (unbound.Count > 0)
+ {
+ offenders.Add($"{control.Id}/{sample.Gallery.Snippet}: {string.Join(", ", unbound)}");
+ }
+ }
+ }
+
+ Assert.AreEqual(
+ 0,
+ offenders.Count,
+ "Published XAML must declare every namespace prefix it binds. Offending samples:\n" + string.Join('\n', offenders));
+ }
+
+ [TestMethod]
+ public void RealRepository_EverySampleCarriesPublishableContent()
+ {
+ // The contract requires a sample to have XAML or code, and its consumer skips any that has
+ // neither. Emitting one anyway would inflate the index with entries that vanish on the
+ // other side, so the exporter leaves them out and this proves it.
+ CatalogGenerationResult result = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot });
+
+ foreach (IndexControl control in result.Index.Controls)
+ {
+ foreach (IndexSample sample in control.Samples)
+ {
+ Assert.IsTrue(
+ !string.IsNullOrWhiteSpace(sample.Xaml) || !string.IsNullOrWhiteSpace(sample.Code),
+ $"{control.Id}/{sample.Gallery.Snippet} has neither XAML nor code and must not be published.");
+
+ Assert.AreEqual(
+ sample.Code is null ? null : "csharp",
+ sample.Language,
+ $"{control.Id}/{sample.Gallery.Snippet} must declare its language exactly when it carries code.");
+ }
+ }
+ }
+
+ [TestMethod]
+ public void RealRepository_NoSampleUsesInlineControlExampleCode()
+ {
+ // ControlExample supports two ways of supplying code: a SampleDefinition snippet bundle,
+ // and inline / property elements. Only the
+ // first is discoverable by the exporter, so an inline example renders correctly in the
+ // gallery while silently missing from the catalog. Every sample now uses SampleDefinition,
+ // and this test keeps it that way: it fails on the first page that reintroduces the inline
+ // form, at authoring time, instead of letting the gap reach consumers of the catalog.
+ //
+ // The pages are parsed rather than text-searched so that commented-out markup does not
+ // count as a real usage.
+ string samplesRoot = Path.Combine(RepoRoot, "WinUIGallery", "Samples");
+ Assert.IsTrue(Directory.Exists(samplesRoot), $"{samplesRoot} is missing.");
+
+ List offenders = [];
+ List unparsable = [];
+ int pagesChecked = 0;
+
+ foreach (string page in Directory.EnumerateFiles(samplesRoot, "*.xaml", SearchOption.AllDirectories))
+ {
+ string relative = Path.GetRelativePath(RepoRoot, page).Replace('\\', '/');
+ XDocument document;
+ try
+ {
+ document = XDocument.Load(page);
+ }
+ catch (System.Xml.XmlException ex)
+ {
+ unparsable.Add($"{relative} ({ex.Message})");
+ continue;
+ }
+
+ pagesChecked++;
+ if (document.Descendants().Any(e =>
+ e.Name.LocalName is "ControlExample.Xaml" or "ControlExample.CSharp"))
+ {
+ offenders.Add(relative);
+ }
+ }
+
+ Assert.AreEqual(0, unparsable.Count, "These sample pages are not well-formed XML: " + string.Join(", ", unparsable));
+ Assert.IsTrue(pagesChecked > 0, $"No sample pages were found under {samplesRoot}.");
+
+ Assert.AreEqual(
+ 0,
+ offenders.Count,
+ "These pages supply code inline, which the catalog exporter cannot see. Move the code into a "
+ + "SampleDefinition snippet bundle (a .txt file with '--- xaml' and optional '--- c#' sections) "
+ + "next to the page: " + string.Join(", ", offenders));
+ }
+
+ [TestMethod]
+ public void RealRepository_HasNoValidationIssues()
+ {
+ // Re-asserts the same validation Generate() already performs, so a failure here reports
+ // clearly as "the real data is invalid" rather than surfacing only via the index diff
+ // above.
+ SampleIndex index = CatalogGenerator.Generate(new CatalogGenerationOptions { RepoRoot = RepoRoot }).Index;
+ Assert.IsTrue(index.ControlCount > 0);
+ Assert.AreEqual(index.ControlCount, index.Controls.Count);
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/SampleBundleParserTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/SampleBundleParserTests.cs
new file mode 100644
index 000000000..1b54c0c97
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/SampleBundleParserTests.cs
@@ -0,0 +1,100 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Pins the bundle format rules the exporter shares with ControlExample.ParseSampleCodeSections.
+/// The catalog's promise is "this is the code the gallery shows", so any divergence between the
+/// two parsers publishes something users never see. These tests encode the rules that are easy
+/// to get subtly wrong.
+///
+[TestClass]
+public sealed class SampleBundleParserTests
+{
+ [TestMethod]
+ public void Parse_ReadsHeaderXamlAndCSharpSections()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- header\nA button.\n--- xaml\n\n--- c#\nvar x = 1;\n");
+
+ Assert.AreEqual("A button.", bundle.Header);
+ Assert.AreEqual("", bundle.Xaml);
+ Assert.AreEqual("var x = 1;", bundle.CSharp);
+ }
+
+ [TestMethod]
+ public void Parse_OmitsSectionsThatAreNotPresent()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- header\nHeader only.\n");
+
+ Assert.AreEqual("Header only.", bundle.Header);
+ Assert.IsNull(bundle.Xaml);
+ Assert.IsNull(bundle.CSharp);
+ }
+
+ [TestMethod]
+ public void Parse_RequiresTheTrailingSpaceInTheSectionMarker()
+ {
+ // The app matches on "--- " exactly, so "---xaml" is body text, not a new section. Getting
+ // this wrong would silently split content that the gallery renders as a single block.
+ SampleBundle bundle = SampleBundleParser.Parse("--- xaml\n\n---xaml\n\n");
+
+ Assert.AreEqual("\n---xaml\n", bundle.Xaml);
+ }
+
+ [TestMethod]
+ public void Parse_TrimsSurroundingBlankLinesButKeepsInteriorOnes()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- xaml\n\n\n\n\n\n");
+
+ Assert.AreEqual("\n\n", bundle.Xaml);
+ }
+
+ [TestMethod]
+ public void Parse_NormalizesCarriageReturns()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- xaml\r\n\r\n\r\n");
+
+ Assert.AreEqual("\n", bundle.Xaml);
+ Assert.IsFalse(bundle.Xaml!.Contains('\r'), "Published code must use LF line endings only.");
+ }
+
+ [TestMethod]
+ public void Parse_MatchesSectionNamesCaseInsensitively()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- Header\nH\n--- XAML\n\n--- C#\nvar x = 1;\n");
+
+ Assert.AreEqual("H", bundle.Header);
+ Assert.AreEqual("", bundle.Xaml);
+ Assert.AreEqual("var x = 1;", bundle.CSharp);
+ }
+
+ [TestMethod]
+ public void Parse_IgnoresUnknownSections()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- notes\nInternal note.\n--- xaml\n\n");
+
+ Assert.AreEqual("", bundle.Xaml);
+ Assert.IsNull(bundle.Header);
+ Assert.IsNull(bundle.CSharp);
+ }
+
+ [TestMethod]
+ public void Parse_IgnoresContentBeforeTheFirstSection()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("stray text\n--- xaml\n\n");
+
+ Assert.AreEqual("", bundle.Xaml);
+ }
+
+ [TestMethod]
+ public void Parse_KeepsTheLastOccurrenceOfARepeatedSection()
+ {
+ SampleBundle bundle = SampleBundleParser.Parse("--- xaml\n\n--- xaml\n\n");
+
+ Assert.AreEqual("", bundle.Xaml);
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/SubstitutionResolverTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/SubstitutionResolverTests.cs
new file mode 100644
index 000000000..342dad2fe
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/SubstitutionResolverTests.cs
@@ -0,0 +1,300 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Xml.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Pins the rules the substitution resolver uses to turn $(Token) placeholders into the values the
+/// gallery shows on first load. The bias throughout is that leaving a token unresolved is safe,
+/// while publishing a value the gallery never shows is not - so most of these tests assert that an
+/// ambiguous case is skipped rather than guessed.
+///
+[TestClass]
+public sealed class SubstitutionResolverTests
+{
+ private const string Header =
+ """
+
+ """;
+
+ private static (XElement Example, XElement Root) Parse(string inner)
+ {
+ XDocument document = XDocument.Parse(Header + inner + "");
+ XElement root = document.Root!;
+ XElement example = root.Descendants().First(e => e.Name.LocalName == "ControlExample");
+ return (example, root);
+ }
+
+ private static Dictionary Map(string inner)
+ {
+ (XElement example, XElement root) = Parse(inner);
+ return SubstitutionResolver.BuildMap(example, root);
+ }
+
+ [TestMethod]
+ public void LiteralValue_IsUsedVerbatimIncludingSurroundingWhitespace()
+ {
+ // Several snippets write DefaultLabelPosition="Right"$(IsSticky), relying on the value to
+ // bring its own separating spaces. Trimming it would produce malformed XAML.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+ """);
+
+ Assert.AreEqual(" IsSticky=\"True\" ", map["IsSticky"]);
+ }
+
+ [TestMethod]
+ public void DisabledSubstitution_ResolvesToEmptyString()
+ {
+ // ControlExampleSubstitution.ValueAsString returns string.Empty when IsEnabled is false.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+ """);
+
+ Assert.AreEqual(string.Empty, map["Extra"]);
+ }
+
+ [TestMethod]
+ public void UnsetGateOnADefaultFalseProperty_ResolvesToEmpty()
+ {
+ // CommandBar.IsSticky defaults to false, and the markup never sets it, so the gallery
+ // renders this substitution as nothing on load. Leaving the token in place would be both
+ // inaccurate and fatal: the value is a whole attribute, so an unresolved token produces
+ // XAML that will not parse, and consumers discard fragments that fail to parse.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual(string.Empty, map["IsSticky"]);
+ }
+
+ [TestMethod]
+ public void UnsetGateOnACheckBox_ResolvesToEmpty()
+ {
+ // The same rule via the most common shape in the gallery: a CheckBox that starts
+ // unchecked, gating an attribute the sample only shows once the box is ticked.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual(string.Empty, map["IsEnabled"]);
+ }
+
+ [TestMethod]
+ public void GateOnACheckedBox_ResolvesToTheValue()
+ {
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual("Initials=\"SB\"", map["Initials"]);
+ }
+
+ [TestMethod]
+ public void UnresolvableIsEnabled_LeavesTokenAlone()
+ {
+ // IsExpanded is not one of the properties whose default is known here, so whether the
+ // gallery shows this value is genuinely unknowable without running the app. Guessing would
+ // invent markup the app never renders, so the token is left for a human to notice.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.IsFalse(map.ContainsKey("Extra"));
+ }
+
+ [TestMethod]
+ public void BoundProperty_ResolvesToTheControlsInitialAttribute()
+ {
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual("12", map["Spacing"]);
+ }
+
+ [TestMethod]
+ public void BoundProperty_WithNoInitialValue_IsLeftUnresolved()
+ {
+ // The control relies on the framework default. Reproducing those defaults would mean
+ // encoding WinUI's type metadata here, and getting one wrong publishes a false value.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.IsFalse(map.ContainsKey("Spacing"));
+ }
+
+ [TestMethod]
+ public void NullableBoolPath_ReadsTheUnderlyingAttribute()
+ {
+ // x:Bind spells a nullable bool as IsChecked.Value, but the markup attribute is IsChecked.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual("True", map["Checked"]);
+ }
+
+ [TestMethod]
+ public void ConverterFunction_IsLeftUnresolved()
+ {
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ """);
+
+ Assert.IsFalse(map.ContainsKey("OnTop"));
+ }
+
+ [TestMethod]
+ public void CastSelectorBinding_ResolvesThroughTheCast()
+ {
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+
+
+
+ """);
+
+ Assert.AreEqual("Multiple", map["Mode"]);
+ }
+
+ [TestMethod]
+ public void SelectedItem_UsesTheItemMarkedIsSelected()
+ {
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+ Red
+ Blue
+
+ """);
+
+ Assert.AreEqual("Blue", map["Tint"]);
+ }
+
+ [TestMethod]
+ public void SelectorWithNoDeclaredSelection_IsLeftUnresolved()
+ {
+ // Such a selector starts empty, so assuming the first item would publish a value the
+ // gallery does not show.
+ Dictionary map = Map(
+ """
+
+
+
+
+
+
+
+
+ """);
+
+ Assert.IsFalse(map.ContainsKey("Tint"));
+ }
+
+ [TestMethod]
+ public void ExampleWithoutSubstitutions_ProducesAnEmptyMap()
+ {
+ Assert.AreEqual(0, Map("").Count);
+ }
+
+ [TestMethod]
+ public void Apply_ReplacesKnownTokensAndPreservesUnknownOnes()
+ {
+ Dictionary map = new(StringComparer.Ordinal) { ["Known"] = "yes" };
+
+ Assert.AreEqual(
+ "a=\"yes\" b=\"$(Unknown)\"",
+ SubstitutionResolver.Apply("a=\"$(Known)\" b=\"$(Unknown)\"", map));
+ }
+
+ [TestMethod]
+ public void Apply_LeavesUnterminatedTokenTextUntouched()
+ {
+ Dictionary map = new(StringComparer.Ordinal) { ["Known"] = "yes" };
+
+ Assert.AreEqual("literal $(Known", SubstitutionResolver.Apply("literal $(Known", map));
+ }
+
+ [TestMethod]
+ public void Apply_WithEmptyMap_ReturnsInputUnchanged()
+ {
+ Assert.AreEqual("$(Anything)", SubstitutionResolver.Apply("$(Anything)", new Dictionary()));
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/TokenFallbackTests.cs b/tests/WinUIGallery.CatalogExporter.Tests/TokenFallbackTests.cs
new file mode 100644
index 000000000..e3a20bd81
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/TokenFallbackTests.cs
@@ -0,0 +1,192 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using WinUIGallery.CatalogExporter;
+
+namespace WinUIGallery.CatalogExporter.Tests;
+
+///
+/// Pins the behaviour of the last step before publication: removing the $(Token) placeholders the
+/// resolver declined to settle.
+///
+/// The guarantee these tests protect is narrow but absolute - published XAML contains no
+/// placeholder - and the way it is kept is by deletion rather than inference. So most of these
+/// assert the shape of what is left behind: the attribute carrying the token is gone, everything
+/// around it is untouched, and the fragment still parses.
+///
+[TestClass]
+public sealed class TokenFallbackTests
+{
+ [TestMethod]
+ public void FragmentWithoutTokens_IsReturnedUnchanged()
+ {
+ const string Xaml = """""";
+
+ Assert.AreEqual(Xaml, TokenFallback.StripFromXaml(Xaml));
+ }
+
+ [TestMethod]
+ public void TokenInAttribute_RemovesTheWholeAttribute()
+ {
+ // X1 falls back to its own default, which is what the gallery shows whenever the slider the
+ // token bound to was never given an initial value.
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("""""", result);
+ }
+
+ [TestMethod]
+ public void TokenInLastAttribute_LeavesASingleSeparatorBeforeTheTagClose()
+ {
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("""""", result);
+ }
+
+ [TestMethod]
+ public void TokenInOnlyAttribute_LeavesTheElementIntact()
+ {
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("", result);
+ Assert.IsTrue(XamlFragment.IsWellFormed(result));
+ }
+
+ [TestMethod]
+ public void TokenEmbeddedInALargerValue_StillRemovesTheWholeAttribute()
+ {
+ // InfoBadge writes Style="{StaticResource $(Style)IconInfoBadgeStyle}". Removing only the
+ // token would leave a StaticResource key that does not exist, which is worse than no Style
+ // at all: it fails at load instead of falling back to the default.
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("""""", result);
+ }
+
+ [TestMethod]
+ public void TwoTokensInOneAttribute_RemoveTheAttributeOnce()
+ {
+ // RadialGradientBrush writes Center="$(CenterX),$(CenterY)"; the overlapping removals must
+ // not cut the surrounding markup twice.
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("""""", result);
+ }
+
+ [TestMethod]
+ public void AttributeOnItsOwnLine_TakesTheBlankLineWithIt()
+ {
+ string result = TokenFallback.StripFromXaml(
+ """
+
+ """);
+
+ Assert.AreEqual(
+ """
+
+ """,
+ result);
+ }
+
+ [TestMethod]
+ public void TokenInElementContent_RemovesOnlyTheTokenText()
+ {
+ // There is no attribute to drop here, so the container keeps its other children and simply
+ // loses the content the gallery injected at runtime.
+ string result = TokenFallback.StripFromXaml(
+ """
+
+ $(MultipleButtonsSecondaryCommands)
+
+ """);
+
+ Assert.AreEqual(
+ """
+
+
+
+ """,
+ result);
+ Assert.IsTrue(XamlFragment.IsWellFormed(result));
+ }
+
+ [TestMethod]
+ public void TokenInsideAComment_IsRemovedWithoutDisturbingTheProse()
+ {
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("", result);
+ }
+
+ [TestMethod]
+ public void AngleBracketInsideAnAttributeValue_DoesNotEndTheTagEarly()
+ {
+ // A naive scan for '>' would treat the comparison as the end of the tag and then mistake
+ // the following attribute for element content, leaving the token in place.
+ string result = TokenFallback.StripFromXaml("""""");
+
+ Assert.AreEqual("""""", result);
+ }
+
+ [TestMethod]
+ public void CrLfSnippet_KeepsItsLineEndings()
+ {
+ string result = TokenFallback.StripFromXaml("\r\n \r\n");
+
+ Assert.AreEqual("\r\n \r\n", result);
+ }
+
+ [TestMethod]
+ public void ATokenStandingInForAWholeAttribute_IsRemovedWithoutBreakingTheTag()
+ {
+ Assert.AreEqual(
+ """""",
+ TokenFallback.StripFromXaml(""""""));
+
+ Assert.AreEqual(
+ "\r\n \r\n",
+ TokenFallback.StripFromXaml("\r\n \r\n"));
+ }
+
+ [TestMethod]
+ public void EveryRemoval_LeavesAWellFormedFragment()
+ {
+ string[] fragments =
+ [
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ ];
+
+ foreach (string fragment in fragments)
+ {
+ string result = TokenFallback.StripFromXaml(fragment);
+
+ Assert.IsFalse(TokenFallback.ContainsToken(result), $"Placeholder survived in: {result}");
+ Assert.IsTrue(XamlFragment.IsWellFormed(result), $"Fragment stopped parsing: {result}");
+ }
+ }
+
+ [TestMethod]
+ public void TokenNames_AreReportedOnceInOrderOfAppearance()
+ {
+ List names = TokenFallback.TokenNames("""""");
+
+ CollectionAssert.AreEqual(new[] { "Slider1", "Slider2" }, names);
+ }
+
+ [TestMethod]
+ public void ContainsToken_IgnoresTextThatMerelyLooksLikeOne()
+ {
+ Assert.IsFalse(TokenFallback.ContainsToken(""""""));
+ Assert.IsFalse(TokenFallback.ContainsToken(null));
+ }
+}
diff --git a/tests/WinUIGallery.CatalogExporter.Tests/WinUIGallery.CatalogExporter.Tests.csproj b/tests/WinUIGallery.CatalogExporter.Tests/WinUIGallery.CatalogExporter.Tests.csproj
new file mode 100644
index 000000000..f5a29a7d3
--- /dev/null
+++ b/tests/WinUIGallery.CatalogExporter.Tests/WinUIGallery.CatalogExporter.Tests.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+ net10.0
+ WinUIGallery.CatalogExporter.Tests
+ enable
+ latest
+ enable
+ false
+ true
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/CatalogExporter/AssemblyInfo.cs b/tools/CatalogExporter/AssemblyInfo.cs
new file mode 100644
index 000000000..047c23fb8
--- /dev/null
+++ b/tools/CatalogExporter/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Runtime.CompilerServices;
+
+[assembly: InternalsVisibleTo("WinUIGallery.CatalogExporter.Tests")]
diff --git a/tools/CatalogExporter/CatalogExporter.csproj b/tools/CatalogExporter/CatalogExporter.csproj
new file mode 100644
index 000000000..7cb8f0fb9
--- /dev/null
+++ b/tools/CatalogExporter/CatalogExporter.csproj
@@ -0,0 +1,23 @@
+
+
+
+
+ Exe
+ net10.0
+ WinUIGallery.CatalogExporter
+ WinUIGallery.CatalogExporter
+ enable
+ latest
+ enable
+ true
+ false
+
+ false
+
+
+
+
diff --git a/tools/CatalogExporter/CatalogGenerator.cs b/tools/CatalogExporter/CatalogGenerator.cs
new file mode 100644
index 000000000..fd46ad104
--- /dev/null
+++ b/tools/CatalogExporter/CatalogGenerator.cs
@@ -0,0 +1,672 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using System.Text.Json;
+using System.Text.RegularExpressions;
+using System.Xml.Linq;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// A single, reportable problem found while validating source data or generating the manifest.
+/// Multiple issues are collected and reported together instead of failing on the first one.
+///
+internal sealed record CatalogIssue(string UniqueId, string Message)
+{
+ public override string ToString() => string.IsNullOrEmpty(UniqueId) ? Message : $"{UniqueId}: {Message}";
+}
+
+/// Thrown by when validation fails.
+internal sealed class CatalogValidationException(IReadOnlyList issues)
+ : Exception("Catalog validation failed:\n" + string.Join('\n', issues.Select(i => " - " + i)))
+{
+ public IReadOnlyList Issues { get; } = issues;
+}
+
+internal sealed class CatalogGenerationOptions
+{
+ /// Absolute path to the repository root (folder containing WinUIGallery.slnx).
+ public required string RepoRoot { get; init; }
+ public string RepoOwner { get; init; } = "microsoft";
+ public string RepoName { get; init; } = "WinUI-Gallery";
+ public string DefaultBranch { get; init; } = "main";
+}
+
+///
+/// The generated index plus any non-fatal problems found on the way.
+///
+/// Warnings are returned rather than thrown because they describe snippets that are correct for
+/// the gallery's own code viewer but cannot be published as paste-ready code — for example a
+/// fragment written as "<Window ...>" to stand in for the reader's own window. Failing the
+/// build on those would block the exporter on authored content that is not wrong.
+///
+internal sealed record CatalogGenerationResult(SampleIndex Index, IReadOnlyList Warnings);
+
+///
+/// Builds the catalog/windows-samples.json manifest from ControlInfoData.json plus the on-disk
+/// WinUIGallery/Samples/<UniqueId>/ folders. See catalog/README.md for the design.
+///
+internal static partial class CatalogGenerator
+{
+ private const string ControlInfoRelativePath = "WinUIGallery/SampleSupport/Data/ControlInfoData.json";
+ private const string SamplesRelativeRoot = "WinUIGallery/Samples";
+
+ /// Root namespace of the gallery itself, which no published snippet can rely on.
+ private const string GalleryRootNamespace = "WinUIGallery";
+
+ ///
+ /// A plain "using Some.Namespace;" directive. Alias and static forms are skipped: the consumer
+ /// re-emits each entry as "using X;", which would not round-trip either of them.
+ ///
+ [GeneratedRegex(@"^\s*using\s+(?!static\b)([A-Za-z_][\w.]*)\s*;", RegexOptions.Multiline)]
+ private static partial Regex UsingDirectiveRegex();
+
+ private static readonly JsonSerializerOptions ReadOptions = new()
+ {
+ PropertyNameCaseInsensitive = true,
+ TypeInfoResolver = CatalogReadContext.Default,
+ };
+
+ public static readonly JsonSerializerOptions WriteOptions = new()
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
+ WriteIndented = true,
+ DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
+ TypeInfoResolver = CatalogWriteContext.Default,
+ };
+
+ /// Reads ControlInfoData.json and the Samples folders and produces validated artifacts.
+ public static CatalogGenerationResult Generate(CatalogGenerationOptions options)
+ {
+ string controlInfoPath = Path.Combine(options.RepoRoot, Normalize(ControlInfoRelativePath));
+ if (!File.Exists(controlInfoPath))
+ {
+ throw new FileNotFoundException($"Could not find ControlInfoData.json at '{controlInfoPath}'.", controlInfoPath);
+ }
+
+ string json = File.ReadAllText(controlInfoPath);
+ ControlInfoRoot? root = JsonSerializer.Deserialize(json, ReadOptions);
+ if (root is null)
+ {
+ throw new InvalidDataException($"'{controlInfoPath}' did not deserialize to a valid ControlInfoData document.");
+ }
+
+ List issues = [];
+ string samplesRoot = Path.Combine(options.RepoRoot, Normalize(SamplesRelativeRoot));
+
+ // Every UniqueId in the file must be unique - collisions would silently shadow items in
+ // the running app too, but we check independently here since the exporter is a separate
+ // source of truth for validation.
+ Dictionary itemsById = new(StringComparer.Ordinal);
+ foreach (ControlInfoGroup group in root.Groups)
+ {
+ foreach (ControlInfoItem item in group.Items)
+ {
+ if (string.IsNullOrWhiteSpace(item.UniqueId))
+ {
+ issues.Add(new CatalogIssue(string.Empty, $"Item with empty UniqueId in group '{group.UniqueId}'."));
+ continue;
+ }
+
+ if (!itemsById.TryAdd(item.UniqueId, item))
+ {
+ issues.Add(new CatalogIssue(item.UniqueId, "Duplicate UniqueId across ControlInfoData.json groups."));
+ }
+ }
+ }
+
+ List controls = [];
+ List warnings = [];
+ foreach (ControlInfoGroup group in root.Groups)
+ {
+ foreach (ControlInfoItem item in group.Items)
+ {
+ if (string.IsNullOrWhiteSpace(item.UniqueId))
+ {
+ continue; // already reported above
+ }
+
+ if (item.Catalog?.Exclude == true)
+ {
+ continue;
+ }
+
+ IndexControl? control = BuildControl(item, group, samplesRoot, itemsById, options, issues, warnings);
+ if (control is not null)
+ {
+ controls.Add(control);
+ }
+ }
+ }
+
+ // Now that every included id is known, validate cross-references (RelatedControls and
+ // Catalog.RelatedSamples) so a typo/rename never silently produces a broken link.
+ HashSet includedIds = new(controls.Select(c => $"{RepoId(options)}#{c.Gallery.UniqueId}"), StringComparer.Ordinal);
+ foreach (IndexControl control in controls)
+ {
+ foreach (string relatedId in control.Gallery.RelatedSamples ?? [])
+ {
+ bool isSameRepo = relatedId.StartsWith(RepoId(options) + "#", StringComparison.Ordinal);
+ if (isSameRepo && !includedIds.Contains(relatedId))
+ {
+ issues.Add(new CatalogIssue(control.Gallery.UniqueId, $"Related sample reference '{relatedId}' does not resolve to an included catalog entry."));
+ }
+ }
+ }
+
+ // Control ids are what a consumer builds its own sample ids from, so a collision would
+ // make two gallery pages indistinguishable. They are lowercased UniqueIds, so this catches
+ // two pages whose ids differ only by case.
+ HashSet controlIds = new(StringComparer.Ordinal);
+ foreach (IndexControl control in controls)
+ {
+ if (!controlIds.Add(control.Id))
+ {
+ issues.Add(new CatalogIssue(control.Gallery.UniqueId, $"Duplicate control id '{control.Id}'."));
+ }
+ }
+
+ // A snippet is the stable identity of a sample within its control, so a page pointing two
+ // ControlExamples at one snippet would publish the same code twice under two names.
+ foreach (IndexControl control in controls)
+ {
+ HashSet snippets = new(StringComparer.Ordinal);
+ foreach (IndexSample sample in control.Samples)
+ {
+ if (!snippets.Add(sample.Gallery.Snippet))
+ {
+ issues.Add(new CatalogIssue(control.Gallery.UniqueId, $"Duplicate snippet '{sample.Gallery.Snippet}'."));
+ }
+ }
+ }
+
+ if (issues.Count > 0)
+ {
+ throw new CatalogValidationException(issues);
+ }
+
+ controls.Sort((a, b) => string.CompareOrdinal(a.Id, b.Id));
+
+ SampleIndex index = new()
+ {
+ Generator = new IndexGeneratorInfo
+ {
+ Repository = $"https://github.com/{options.RepoOwner}/{options.RepoName}",
+ DefaultBranch = options.DefaultBranch,
+ },
+ ControlCount = controls.Count,
+ Controls = controls,
+ };
+
+ return new CatalogGenerationResult(index, warnings);
+ }
+
+ private static IndexControl? BuildControl(
+ ControlInfoItem item,
+ ControlInfoGroup group,
+ string samplesRoot,
+ IReadOnlyDictionary itemsById,
+ CatalogGenerationOptions options,
+ List issues,
+ List warnings)
+ {
+ string folder = Path.Combine(samplesRoot, item.UniqueId);
+ if (!Directory.Exists(folder))
+ {
+ issues.Add(new CatalogIssue(item.UniqueId, $"No sample folder found at 'WinUIGallery/Samples/{item.UniqueId}'."));
+ return null;
+ }
+
+ string[] entries = Directory.GetFiles(folder);
+ string expectedPageFile = item.UniqueId + "Page.xaml";
+ string expectedCodeBehindFile = item.UniqueId + "Page.xaml.cs";
+
+ string? pageFile = FindExactCase(entries, expectedPageFile);
+ if (pageFile is null)
+ {
+ issues.Add(new CatalogIssue(
+ item.UniqueId,
+ $"Expected page file '{expectedPageFile}' was not found (case-exact) in 'WinUIGallery/Samples/{item.UniqueId}'."));
+ return null;
+ }
+
+ string? codeBehindFile = FindExactCase(entries, expectedCodeBehindFile);
+
+ List samples = ExtractSamples(pageFile, item.UniqueId, folder, options, issues, warnings);
+
+ // Namespace imports every sample shares are hoisted to the control, which is exactly the
+ // default the contract describes; a sample needing a different set keeps its own.
+ List? sharedImports = HoistSharedImports(samples);
+
+ return new IndexControl
+ {
+ Id = ToControlId(item.UniqueId),
+ Name = item.Title,
+ Description = NullIfEmpty(item.Subtitle),
+ Details = NullIfEmpty(item.Description),
+ ApiNamespace = NullIfEmpty(item.ApiNamespace),
+ RelatedControls = NullIfEmpty(ResolveRelatedControlNames(item, itemsById)),
+ XmlnsImports = sharedImports,
+ Usings = NullIfEmpty(CollectUsings(codeBehindFile, samples)),
+ Keywords = NullIfEmpty(item.BaseClasses),
+ CuratedKeywords = BuildCuratedKeywords(item),
+ Docs = item.Docs.Count == 0
+ ? null
+ : item.Docs.Select(d => new IndexDocLink { Title = d.Title, Uri = d.Uri }).ToList(),
+ Gallery = new IndexControlGallery
+ {
+ UniqueId = item.UniqueId,
+ Group = new IndexGroupRef { Id = group.UniqueId, Title = group.Title },
+ Page = ToRepoRelative(pageFile, options.RepoRoot),
+ CodeBehind = codeBehindFile is null ? null : ToRepoRelative(codeBehindFile, options.RepoRoot),
+ BaseClasses = NullIfEmpty(item.BaseClasses),
+ Badges = BuildBadges(item),
+ RelatedSamples = BuildRelatedSamples(item, options),
+ },
+ Samples = samples,
+ };
+ }
+
+ ///
+ /// Lowercases a UniqueId into the short, URL-safe form the contract asks for. Ids are scoped
+ /// to a source there, so "Button" is unambiguous without repeating the repository in it.
+ ///
+ private static string ToControlId(string uniqueId) => uniqueId.ToLowerInvariant();
+
+ ///
+ /// Search terms the gallery's own authors wrote in ControlInfoData.json. Tags and aliases are
+ /// merged because both are hand-written there and the contract has one slot for author terms.
+ ///
+ private static List? BuildCuratedKeywords(ControlInfoItem item)
+ {
+ List keywords = [];
+ keywords.AddRange(item.Tags ?? []);
+ keywords.AddRange(item.Catalog?.Aliases ?? []);
+
+ return keywords.Count == 0
+ ? null
+ : keywords.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
+ }
+
+ ///
+ /// Moves namespace imports up to the control when every sample needs the same ones, and clears
+ /// them from the samples. When the samples differ, each keeps its own and the control declares
+ /// none — the contract treats a sample's own list as a full override, not an addition, so a
+ /// partial control-level list would quietly drop imports for the samples that override it.
+ ///
+ private static List? HoistSharedImports(List samples)
+ {
+ List withXaml = samples.Where(s => s.Xaml is not null).ToList();
+ if (withXaml.Count == 0)
+ {
+ return null;
+ }
+
+ List first = withXaml[0].XmlnsImports ?? [];
+ bool allMatch = withXaml.All(s => (s.XmlnsImports ?? []).SequenceEqual(first, StringComparer.Ordinal));
+ if (!allMatch || first.Count == 0)
+ {
+ return null;
+ }
+
+ foreach (IndexSample sample in samples)
+ {
+ sample.XmlnsImports = null;
+ }
+
+ return first;
+ }
+
+ ///
+ /// The contract's "relatedControls" is display names, but ControlInfoData.json stores
+ /// UniqueIds in that field. Resolving each one keeps consumers from rendering an internal id
+ /// like "XamlStyles" where a reader expects "Style". An id that does not resolve is passed
+ /// through unchanged so a stale reference stays visible rather than silently disappearing.
+ ///
+ private static List ResolveRelatedControlNames(
+ ControlInfoItem item,
+ IReadOnlyDictionary itemsById)
+ {
+ List names = [];
+ foreach (string relatedControl in item.RelatedControls)
+ {
+ names.Add(itemsById.TryGetValue(relatedControl, out ControlInfoItem? related)
+ && !string.IsNullOrWhiteSpace(related.Title)
+ ? related.Title
+ : relatedControl);
+ }
+
+ return names;
+ }
+
+ ///
+ /// The namespaces a control's published C# assumes, taken from the imports its page's
+ /// code-behind was written against. Over-collecting is deliberate: an unused "using" compiles
+ /// harmlessly, while a missing one does not.
+ ///
+ /// The gallery's own namespaces are excluded, because prepending something like
+ /// "using WinUIGallery.Helpers;" would guarantee the failure this field exists to prevent.
+ ///
+ private static List CollectUsings(string? codeBehindFile, List samples)
+ {
+ if (codeBehindFile is null || !samples.Any(s => !string.IsNullOrWhiteSpace(s.Code)))
+ {
+ return [];
+ }
+
+ SortedSet namespaces = new(StringComparer.Ordinal);
+ foreach (Match match in UsingDirectiveRegex().Matches(File.ReadAllText(codeBehindFile)))
+ {
+ string ns = match.Groups[1].Value;
+ if (ns != GalleryRootNamespace && !ns.StartsWith(GalleryRootNamespace + ".", StringComparison.Ordinal))
+ {
+ namespaces.Add(ns);
+ }
+ }
+
+ return [.. namespaces];
+ }
+
+ private static List? BuildRelatedSamples(ControlInfoItem item, CatalogGenerationOptions options)
+ {
+ List related = [];
+ foreach (string relatedControl in item.RelatedControls)
+ {
+ related.Add($"{RepoId(options)}#{relatedControl}");
+ }
+
+ if (item.Catalog?.RelatedSamples is { Length: > 0 } extra)
+ {
+ related.AddRange(extra);
+ }
+
+ if (related.Count == 0)
+ {
+ return null;
+ }
+
+ return related.Distinct(StringComparer.Ordinal).OrderBy(r => r, StringComparer.Ordinal).ToList();
+ }
+
+ private static List? BuildBadges(ControlInfoItem item)
+ {
+ List badges = [];
+ if (item.IsNew)
+ {
+ badges.Add("New");
+ }
+
+ if (item.IsUpdated)
+ {
+ badges.Add("Updated");
+ }
+
+ if (item.IsPreview)
+ {
+ badges.Add("Preview");
+ }
+
+ return badges.Count == 0 ? null : badges;
+ }
+
+ private static List ExtractSamples(
+ string pageFile,
+ string uniqueId,
+ string folder,
+ CatalogGenerationOptions options,
+ List issues,
+ List warnings)
+ {
+ List samples = [];
+ string[] entries = Directory.GetFiles(folder);
+ string folderName = Path.GetFileName(folder);
+
+ // The page is parsed rather than pattern-matched so that each snippet can be tied to the
+ // ControlExample that owns it, which is what makes its $(Token) substitutions resolvable.
+ // Parsing also ignores commented-out markup, which a text scan would treat as real.
+ XDocument page;
+ try
+ {
+ page = XDocument.Load(pageFile);
+ }
+ catch (System.Xml.XmlException ex)
+ {
+ issues.Add(new CatalogIssue(uniqueId, $"{Path.GetFileName(pageFile)} is not well-formed XML: {ex.Message}"));
+ return samples;
+ }
+
+ XElement? pageRoot = page.Root;
+ if (pageRoot is null)
+ {
+ return samples;
+ }
+
+ Dictionary pageDeclarations = XamlFragment.ReadPageDeclarations(pageRoot);
+
+ foreach (XElement controlExample in pageRoot.DescendantsAndSelf().Where(e => e.Name.LocalName == "ControlExample"))
+ {
+ string? rawPath = (string?)controlExample.Attribute("SampleDefinition");
+ if (string.IsNullOrWhiteSpace(rawPath))
+ {
+ continue;
+ }
+
+ // The directory portion is not decoration: ControlExample loads the bundle as
+ // "Samples/", so a value naming the wrong folder fails at runtime even
+ // when a file of that name happens to sit next to the page. Checking only the file name
+ // would let that typo through here and leave it to surface as an empty code viewer.
+ string[] segments = rawPath!.Replace('\\', '/').Split('/', StringSplitOptions.RemoveEmptyEntries);
+ if (segments.Length != 2 || !string.Equals(segments[0], folderName, StringComparison.Ordinal))
+ {
+ issues.Add(new CatalogIssue(uniqueId, $"SampleDefinition '{rawPath}' must be '{folderName}\\.txt'; the gallery resolves it under Samples\\ and would fail to load it as written."));
+ continue;
+ }
+
+ string fileName = segments[1];
+
+ string? bundlePath = FindExactCase(entries, fileName);
+ if (bundlePath is null)
+ {
+ issues.Add(new CatalogIssue(uniqueId, $"SampleDefinition references '{fileName}' which was not found (case-exact) next to the page."));
+ continue;
+ }
+
+ SampleBundle bundle = SampleBundleParser.Parse(File.ReadAllText(bundlePath));
+
+ // A scenario legitimately has no code: either the page hides the viewer entirely
+ // (SourceCodeVisibility="Collapsed"), or it swaps ControlExample.XamlSource at runtime,
+ // so no single snippet represents it. The contract requires a sample to carry XAML or
+ // code, so there is nothing to publish and it is left out.
+ if (bundle.Xaml is null && bundle.CSharp is null)
+ {
+ continue;
+ }
+
+ Dictionary substitutions = SubstitutionResolver.BuildMap(controlExample, pageRoot);
+
+ string? xaml = NullIfEmpty(SubstitutionResolver.Apply(bundle.Xaml ?? string.Empty, substitutions));
+ string? code = NullIfEmpty(SubstitutionResolver.Apply(bundle.CSharp ?? string.Empty, substitutions));
+
+ // The resolver leaves a token alone rather than guess at it, which is right for accuracy
+ // but leaves markup a consumer cannot paste. Whatever it declined to settle is dropped
+ // here, along with the attribute carrying it, so published XAML never contains a
+ // placeholder.
+ List? droppedPlaceholders = null;
+ if (TokenFallback.ContainsToken(xaml))
+ {
+ List names = TokenFallback.TokenNames(xaml!);
+ string? stripped = NullIfEmpty(TokenFallback.StripFromXaml(xaml!));
+
+ // A token standing in for an element name, as in "<$(EasingFunction)/>", has no
+ // attribute to drop and no default to fall back to. Nothing is claimed in that case:
+ // the fragment simply does not parse and the check below omits it, exactly as it did
+ // before this fallback existed.
+ if (!TokenFallback.ContainsToken(stripped))
+ {
+ droppedPlaceholders = names;
+ xaml = stripped;
+ warnings.Add(new CatalogIssue(uniqueId, $"'{fileName}' had unresolved placeholders ({string.Join(", ", names)}); the attributes carrying them were dropped."));
+ }
+ }
+
+ // Consumers parse the XAML and discard whatever fails, so publishing a fragment that
+ // cannot parse would advertise code that never arrives. Dropping it here instead keeps
+ // the index honest and makes the reason visible in the build output.
+ bool malformed = xaml is not null && !XamlFragment.IsWellFormed(xaml);
+ if (malformed)
+ {
+ warnings.Add(new CatalogIssue(uniqueId, $"'{fileName}' XAML is not a well-formed fragment and was omitted."));
+ xaml = null;
+ }
+
+ // A prefix the page never declares cannot be turned into an import, and DetectImports
+ // drops it rather than inventing a URI. That leaves a fragment referencing a namespace
+ // nothing binds: it parses here and on the consumer's side, because both synthesize
+ // declarations, and then fails the moment a reader pastes it with the imports this index
+ // published. Omitting the XAML is the same degradation a malformed fragment gets, for
+ // the same reason - publishing it would advertise code that does not work on arrival.
+ List unboundPrefixes = xaml is null ? [] : XamlFragment.UnresolvedPrefixes(xaml, pageDeclarations);
+ if (unboundPrefixes.Count > 0)
+ {
+ warnings.Add(new CatalogIssue(uniqueId, $"'{fileName}' XAML uses namespace prefixes its page does not declare ({string.Join(", ", unboundPrefixes)}) and was omitted."));
+ xaml = null;
+ }
+
+ // Nothing below may publish a placeholder. The fallback and the parse check together are
+ // meant to make this unreachable, so failing here is deliberate: the index's promise is
+ // that its XAML pastes as published, and shipping a token would quietly break it.
+ if (TokenFallback.ContainsToken(xaml))
+ {
+ issues.Add(new CatalogIssue(uniqueId, $"'{fileName}' still contains unresolved placeholders ({string.Join(", ", TokenFallback.TokenNames(xaml!))}) after fallback removal."));
+ continue;
+ }
+
+ if (xaml is null && code is null)
+ {
+ continue;
+ }
+
+ // C# gets no such gate, and the asymmetry is deliberate. The XAML fallback works only
+ // because deleting an attribute leaves the property at its own default; C# has no
+ // construct whose absence means "default", and the tokens that occur here sit in
+ // identifier fragments, fixed-arity argument lists, and whole statements, none of which
+ // survive having the token cut out. So they ship as written, and the names are declared
+ // instead, so a consumer can tell templated code from code it can paste.
+ List? codePlaceholders = TokenFallback.ContainsToken(code)
+ ? TokenFallback.TokenNames(code!)
+ : null;
+
+ samples.Add(new IndexSample
+ {
+ Header = NullIfEmpty(bundle.Header) ?? DeriveScenarioName(fileName, uniqueId),
+ Xaml = xaml,
+ Code = code,
+ Language = code is null ? null : "csharp",
+ XmlnsImports = xaml is null ? null : NullIfEmpty(XamlFragment.DetectImports(xaml, pageDeclarations)),
+ Gallery = new IndexSampleGallery
+ {
+ Snippet = fileName,
+ Source = ToRepoRelative(bundlePath, options.RepoRoot),
+ Name = DeriveScenarioName(fileName, uniqueId),
+ XamlOmittedAsMalformed = malformed ? true : null,
+ XamlOmittedUnboundPrefixes = unboundPrefixes.Count == 0 ? null : unboundPrefixes,
+ XamlPlaceholdersDropped = xaml is null ? null : droppedPlaceholders,
+ CodePlaceholdersPresent = codePlaceholders,
+ },
+ });
+ }
+
+ // Page order is preserved deliberately: it is the order a visitor sees, and the contract's
+ // consumer numbers samples positionally, so sorting them would renumber ids whenever a
+ // ControlExample is inserted.
+ return samples;
+ }
+
+ ///
+ /// Snippet files are named "<UniqueId><Scenario>.txt" by convention (e.g.
+ /// "ButtonBuiltInStyles.txt" for the "Button" sample). Strip the UniqueId prefix and the
+ /// extension, then insert spaces before capitals, to get a human-readable scenario name.
+ /// Falls back to the file name (without extension) when the convention isn't followed.
+ ///
+ private static string DeriveScenarioName(string fileName, string uniqueId)
+ {
+ string withoutExtension = Path.GetFileNameWithoutExtension(fileName);
+ string suffix = withoutExtension.StartsWith(uniqueId, StringComparison.OrdinalIgnoreCase)
+ ? withoutExtension[uniqueId.Length..]
+ : withoutExtension;
+
+ if (string.IsNullOrWhiteSpace(suffix))
+ {
+ return uniqueId;
+ }
+
+ StringBuilder sb = new();
+ for (int i = 0; i < suffix.Length; i++)
+ {
+ char c = suffix[i];
+ if (i > 0 && char.IsUpper(c) && !char.IsUpper(suffix[i - 1]))
+ {
+ sb.Append(' ');
+ }
+
+ sb.Append(c);
+ }
+
+ return sb.ToString();
+ }
+
+ private static string? FindExactCase(string[] filesInFolder, string expectedFileName)
+ {
+ foreach (string file in filesInFolder)
+ {
+ string name = Path.GetFileName(file);
+ if (string.Equals(name, expectedFileName, StringComparison.Ordinal))
+ {
+ return file;
+ }
+ }
+
+ return null;
+ }
+
+ private static string ToRepoRelative(string absolutePath, string repoRoot)
+ {
+ string relative = Path.GetRelativePath(repoRoot, absolutePath);
+ return relative.Replace(Path.DirectorySeparatorChar, '/').Replace(Path.AltDirectorySeparatorChar, '/');
+ }
+
+ private static string RepoId(CatalogGenerationOptions options) => $"{options.RepoOwner}/{options.RepoName}";
+
+ private static string Normalize(string relativePath) => relativePath.Replace('/', Path.DirectorySeparatorChar);
+
+ private static string? NullIfEmpty(string? value) => string.IsNullOrEmpty(value) ? null : value;
+
+ private static List? NullIfEmpty(string[]? value) => value is null || value.Length == 0 ? null : [.. value];
+
+ private static List? NullIfEmpty(List value) => value.Count == 0 ? null : value;
+
+ /// Serializes the index deterministically (stable property/array order, LF line endings).
+ public static string Serialize(SampleIndex index)
+ {
+ string json = JsonSerializer.Serialize(index, WriteOptions);
+ return json.Replace("\r\n", "\n").TrimEnd('\n') + "\n";
+ }
+
+ /// Walks up from to find the repo root (WinUIGallery.slnx).
+ public static string FindRepoRoot(string startDirectory)
+ {
+ DirectoryInfo? dir = new(startDirectory);
+ while (dir is not null)
+ {
+ if (File.Exists(Path.Combine(dir.FullName, "WinUIGallery.slnx")))
+ {
+ return dir.FullName;
+ }
+
+ dir = dir.Parent;
+ }
+
+ throw new DirectoryNotFoundException($"Could not locate WinUIGallery.slnx above '{startDirectory}'.");
+ }
+}
diff --git a/tools/CatalogExporter/CatalogJsonContext.cs b/tools/CatalogExporter/CatalogJsonContext.cs
new file mode 100644
index 000000000..8cc3c5770
--- /dev/null
+++ b/tools/CatalogExporter/CatalogJsonContext.cs
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Source-generated metadata for reading ControlInfoData.json, matching the pattern the gallery
+/// and the navigation source generator already use for the same file
+/// (WinUIGallery/Models/ControlInfoData.cs and
+/// WinUIGallery.SourceGenerator/ControlInfoData.cs).
+///
+///
+/// Serializer behaviour deliberately stays on CatalogGenerator.ReadOptions rather than on a
+/// JsonSourceGenerationOptions attribute here. Declaring it in both places would create two
+/// definitions of the same thing that are free to drift, and the options object is the one the call
+/// sites pass and the conformance tests inspect.
+///
+[JsonSerializable(typeof(ControlInfoRoot))]
+internal partial class CatalogReadContext : JsonSerializerContext
+{
+}
+
+///
+/// Source-generated metadata for writing catalog/windows-samples.json.
+///
+///
+/// As with , the naming policy, indentation, and null handling
+/// remain on . That matters more here: the emitted
+/// field names are part of a published contract, and ContractConformanceTests derives the
+/// names it expects from that options object, so keeping it authoritative is what lets the test
+/// verify the writer rather than a copy of the writer's configuration.
+///
+[JsonSerializable(typeof(SampleIndex))]
+internal partial class CatalogWriteContext : JsonSerializerContext
+{
+}
diff --git a/tools/CatalogExporter/CatalogModels.cs b/tools/CatalogExporter/CatalogModels.cs
new file mode 100644
index 000000000..1d1be5c5f
--- /dev/null
+++ b/tools/CatalogExporter/CatalogModels.cs
@@ -0,0 +1,222 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text.Json.Serialization;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Root document for catalog/windows-samples.json.
+///
+/// The shape is not this repository's invention: it is the published "WinUI sample index" contract
+/// defined by microsoft/winappCli (see ), which already has a working consumer
+/// and a second publisher (microsoft-ui-reactor). Emitting that contract directly is what lets a
+/// tool read this file without writing a WinUI-Gallery-specific parser, and is also why the code
+/// is inline here rather than in a sibling file: the contract is built around a consumer making a
+/// single HTTP request.
+///
+/// The contract allows additional properties, so gallery-specific provenance it has no slot for is
+/// carried under a gallery object on each control and sample. It is grouped rather than
+/// scattered so a reader can tell at a glance which fields are the shared contract and which are
+/// ours.
+///
+internal sealed class SampleIndex
+{
+ [JsonPropertyName("$schema")]
+ public string Schema { get; set; } = "https://raw.githubusercontent.com/microsoft/winappCli/main/docs/winui-sample-index.schema.json";
+
+ /// Contract version. Version 1 is the only value the schema accepts.
+ public int SchemaVersion { get; set; } = 1;
+
+ ///
+ /// Identifies the publisher to consumers. "gallery" is the value winappCli already uses for
+ /// this repository, so it is fixed rather than derived from the repository name.
+ ///
+ public string Source { get; set; } = "gallery";
+
+ ///
+ /// Gallery-specific provenance. Deliberately carries no timestamp: the file is committed and
+ /// CI re-runs the generator to check it is current, so a generation time would make every run
+ /// differ and turn that check into constant churn.
+ ///
+ public IndexGeneratorInfo Generator { get; set; } = new();
+
+ public int ControlCount { get; set; }
+
+ public List Controls { get; set; } = [];
+}
+
+internal sealed class IndexGeneratorInfo
+{
+ public string Tool { get; set; } = "tools/CatalogExporter";
+ public string Command { get; set; } = "dotnet run --project tools/CatalogExporter -- generate";
+ public string Repository { get; set; } = string.Empty;
+ public string DefaultBranch { get; set; } = string.Empty;
+ public string License { get; set; } = "MIT";
+}
+
+/// One gallery sample page, expressed as a control in the shared contract.
+internal sealed class IndexControl
+{
+ ///
+ /// Lowercased . The contract scopes ids to a source
+ /// rather than globally, and the consumer builds per-sample ids as "{id}-{n}", so a short
+ /// URL-safe token is used here instead of an "owner/repo#Name" form.
+ ///
+ public string Id { get; set; } = string.Empty;
+
+ public string Name { get; set; } = string.Empty;
+
+ /// One-line summary (ControlInfoData Subtitle).
+ public string? Description { get; set; }
+
+ /// Long-form prose (ControlInfoData Description).
+ public string? Details { get; set; }
+
+ public string? ApiNamespace { get; set; }
+
+ /// Display names of related controls, per the contract — not source-qualified ids.
+ public List? RelatedControls { get; set; }
+
+ ///
+ /// Namespace declarations shared by every sample below. A sample needing a different set
+ /// carries its own; the contract treats this as the default for the ones that do not.
+ ///
+ public List? XmlnsImports { get; set; }
+
+ ///
+ /// Namespaces the control's C# samples assume are imported. The consumer prepends these as
+ /// "using X;" lines so a snippet compiles on its own, which is why they are not repeated
+ /// inside each sample's code.
+ ///
+ public List? Usings { get; set; }
+
+ /// Supplementary, derived search terms.
+ public List? Keywords { get; set; }
+
+ ///
+ /// Search terms written by the sample's own author in ControlInfoData.json. Kept separate from
+ /// because the consumer weighs first-hand terms more heavily.
+ ///
+ public List? CuratedKeywords { get; set; }
+
+ public List? Docs { get; set; }
+
+ public IndexControlGallery Gallery { get; set; } = new();
+
+ ///
+ /// The control's samples in page order — the order a visitor sees them in the gallery.
+ /// Ordering is significant: the consumer numbers samples positionally, so appending a
+ /// ControlExample is safe while reordering renumbers the ones after it.
+ ///
+ public List Samples { get; set; } = [];
+}
+
+/// Gallery-specific provenance that the shared contract has no field for.
+internal sealed class IndexControlGallery
+{
+ /// Original WinUI Gallery UniqueId from ControlInfoData.json.
+ public string UniqueId { get; set; } = string.Empty;
+
+ public IndexGroupRef Group { get; set; } = new();
+
+ /// Repository-relative path to the sample page.
+ public string Page { get; set; } = string.Empty;
+
+ public string? CodeBehind { get; set; }
+
+ public List? BaseClasses { get; set; }
+
+ /// "New", "Updated" and/or "Preview", as shown on the gallery's home page.
+ public List? Badges { get; set; }
+
+ /// Source-qualified ids of related samples, for callers that need to resolve links.
+ public List? RelatedSamples { get; set; }
+}
+
+internal sealed class IndexGroupRef
+{
+ public string Id { get; set; } = string.Empty;
+ public string Title { get; set; } = string.Empty;
+}
+
+internal sealed class IndexDocLink
+{
+ public string Title { get; set; } = string.Empty;
+ public string Uri { get; set; } = string.Empty;
+}
+
+///
+/// One scenario from a page, expressed as a sample in the shared contract. The contract requires
+/// at least one of or to be present and non-empty, so a
+/// scenario with neither is left out of the index entirely.
+///
+internal sealed class IndexSample
+{
+ public string? Header { get; set; }
+
+ ///
+ /// XAML as the gallery renders it on load, with $(Token) substitutions already applied.
+ /// Guaranteed to contain no unresolved placeholder: anything the resolver declined to settle has
+ /// had its attribute removed, so the fragment is always pasteable as published.
+ /// Omitted when the snippet is not a well-formed XML fragment, because the consumer validates
+ /// this and silently discards whatever fails — so publishing it would advertise code that
+ /// never actually arrives.
+ ///
+ public string? Xaml { get; set; }
+
+ public string? Code { get; set; }
+
+ /// Set to "csharp" whenever is present; the only value version 1 accepts.
+ public string? Language { get; set; }
+
+ public List? XmlnsImports { get; set; }
+
+ public IndexSampleGallery Gallery { get; set; } = new();
+}
+
+internal sealed class IndexSampleGallery
+{
+ ///
+ /// Snippet file name. Unlike the sample's position, this survives insertion and reordering, so
+ /// it is the stable way to refer to one scenario across regenerations.
+ ///
+ public string Snippet { get; set; } = string.Empty;
+
+ /// Repository-relative path to the bundle this content was parsed from.
+ public string Source { get; set; } = string.Empty;
+
+ /// Name derived from the snippet file name, used when the bundle declares no header.
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// True when the snippet's XAML was left out because it is not a well-formed fragment. Kept in
+ /// the index so the omission is visible to a reader rather than looking like a sample that
+ /// simply has no XAML.
+ ///
+ public bool? XamlOmittedAsMalformed { get; set; }
+
+ ///
+ /// Namespace prefixes the snippet's XAML binds to that its page never declares. No import can
+ /// be published for them, so the fragment would arrive referencing a namespace nothing binds;
+ /// the XAML is omitted for that reason and the prefixes are named here so the omission reads as
+ /// a known gap in the snippet rather than a sample that simply has no XAML.
+ ///
+ public List? XamlOmittedUnboundPrefixes { get; set; }
+
+ ///
+ /// Attributes dropped from the XAML because they carried a $(Token) the resolver could not
+ /// settle. The property falls back to its own default, which is what the gallery shows in this
+ /// situation anyway, but the names are published so the omission is inspectable rather than
+ /// invisible.
+ ///
+ public List? XamlPlaceholdersDropped { get; set; }
+
+ ///
+ /// Names of $(Token) placeholders still present in this sample's C#. Unlike
+ /// , which lists tokens already removed and guarantees
+ /// clean output, this warns that the published code is NOT pasteable as-is: C# has no
+ /// construct whose absence yields a default, so the tokens cannot be deleted safely.
+ ///
+ public List? CodePlaceholdersPresent { get; set; }
+}
diff --git a/tools/CatalogExporter/Program.cs b/tools/CatalogExporter/Program.cs
new file mode 100644
index 000000000..d56b46c70
--- /dev/null
+++ b/tools/CatalogExporter/Program.cs
@@ -0,0 +1,95 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Regenerates or verifies the generated sample index.
+///
+/// Usage:
+/// dotnet run --project tools/CatalogExporter -- generate [--repo-root <path>]
+/// dotnet run --project tools/CatalogExporter -- check [--repo-root <path>]
+///
+/// "generate" writes catalog/windows-samples.json. "check" regenerates it in memory and fails
+/// (non-zero exit code) if the committed file is stale or missing, without modifying anything on
+/// disk.
+///
+internal static class Program
+{
+ private const string IndexRelativePath = "catalog/windows-samples.json";
+
+ private static int Main(string[] args)
+ {
+ if (args.Length == 0 || (args[0] != "generate" && args[0] != "check"))
+ {
+ Console.Error.WriteLine("Usage: dotnet run --project tools/CatalogExporter -- [--repo-root ]");
+ return 2;
+ }
+
+ string command = args[0];
+ string repoRoot = ParseRepoRoot(args) ?? CatalogGenerator.FindRepoRoot(Directory.GetCurrentDirectory());
+
+ CatalogGenerationOptions options = new() { RepoRoot = repoRoot };
+
+ CatalogGenerationResult result;
+ try
+ {
+ result = CatalogGenerator.Generate(options);
+ }
+ catch (CatalogValidationException ex)
+ {
+ Console.Error.WriteLine(ex.Message);
+ return 1;
+ }
+
+ string content = CatalogGenerator.Serialize(result.Index);
+ string absolutePath = Absolute(repoRoot, IndexRelativePath);
+ int sampleCount = result.Index.Controls.Sum(c => c.Samples.Count);
+
+ foreach (CatalogIssue warning in result.Warnings)
+ {
+ Console.WriteLine($"warning: {warning}");
+ }
+
+ if (command == "generate")
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(absolutePath)!);
+ File.WriteAllText(absolutePath, content);
+
+ Console.WriteLine($"Wrote {result.Index.ControlCount} controls and {sampleCount} samples to {IndexRelativePath}.");
+ return 0;
+ }
+
+ // command == "check"
+ if (!File.Exists(absolutePath))
+ {
+ Console.Error.WriteLine($"{IndexRelativePath} does not exist. Run 'generate' and commit the result.");
+ return 1;
+ }
+
+ if (File.ReadAllText(absolutePath).Replace("\r\n", "\n") != content)
+ {
+ Console.Error.WriteLine($"{IndexRelativePath} is stale. Run 'dotnet run --project tools/CatalogExporter -- generate' and commit the result.");
+ return 1;
+ }
+
+ Console.WriteLine($"Index is up to date ({result.Index.ControlCount} controls, {sampleCount} samples).");
+ return 0;
+ }
+
+ private static string Absolute(string repoRoot, string relativePath) =>
+ Path.Combine(repoRoot, relativePath.Replace('/', Path.DirectorySeparatorChar));
+
+ private static string? ParseRepoRoot(string[] args)
+ {
+ for (int i = 1; i < args.Length - 1; i++)
+ {
+ if (args[i] == "--repo-root")
+ {
+ return Path.GetFullPath(args[i + 1]);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/tools/CatalogExporter/SampleBundle.cs b/tools/CatalogExporter/SampleBundle.cs
new file mode 100644
index 000000000..9b6975f08
--- /dev/null
+++ b/tools/CatalogExporter/SampleBundle.cs
@@ -0,0 +1,82 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// The parsed contents of a SampleDefinition .txt bundle: the prose header shown above the
+/// scenario plus the XAML and/or C# rendered in its code viewer. Any section may be absent.
+///
+internal sealed record SampleBundle(string? Header, string? Xaml, string? CSharp);
+
+///
+/// Parses SampleDefinition .txt bundles.
+///
+/// This deliberately mirrors ControlExample.ParseSampleCodeSections in
+/// WinUIGallery/Controls/ControlExample.xaml.cs, which is the source of truth for the format.
+/// The exporter has to agree with it exactly, because the catalog's promise is "this is the code
+/// the gallery shows for this scenario" - if the two parsers diverge, the catalog silently
+/// publishes something the app never renders. Keep them in sync.
+///
+internal static class SampleBundleParser
+{
+ /// Section lines are "--- name"; the trailing space is part of the marker.
+ private const string SectionMarker = "--- ";
+
+ public static SampleBundle Parse(string content)
+ {
+ string? header = null;
+ string? xaml = null;
+ string? csharp = null;
+ string? currentSection = null;
+ List currentLines = [];
+
+ foreach (string rawLine in content.Split('\n'))
+ {
+ string trimmed = rawLine.TrimEnd('\r');
+ if (trimmed.StartsWith(SectionMarker, StringComparison.Ordinal))
+ {
+ SaveSection(currentSection, currentLines, ref header, ref xaml, ref csharp);
+ currentSection = trimmed[SectionMarker.Length..].Trim();
+ currentLines = [];
+ }
+ else
+ {
+ currentLines.Add(trimmed);
+ }
+ }
+
+ SaveSection(currentSection, currentLines, ref header, ref xaml, ref csharp);
+
+ return new SampleBundle(header, xaml, csharp);
+ }
+
+ private static void SaveSection(
+ string? sectionName,
+ List lines,
+ ref string? header,
+ ref string? xaml,
+ ref string? csharp)
+ {
+ if (sectionName is null)
+ {
+ return;
+ }
+
+ // Unrecognized section names are ignored rather than reported: the app ignores them too,
+ // so they cannot affect what a user sees.
+ string content = string.Join('\n', lines).Trim();
+ if (sectionName.Equals("header", StringComparison.OrdinalIgnoreCase))
+ {
+ header = content;
+ }
+ else if (sectionName.Equals("xaml", StringComparison.OrdinalIgnoreCase))
+ {
+ xaml = content;
+ }
+ else if (sectionName.Equals("c#", StringComparison.OrdinalIgnoreCase))
+ {
+ csharp = content;
+ }
+ }
+}
diff --git a/tools/CatalogExporter/SourceModels.cs b/tools/CatalogExporter/SourceModels.cs
new file mode 100644
index 000000000..d884b8665
--- /dev/null
+++ b/tools/CatalogExporter/SourceModels.cs
@@ -0,0 +1,86 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Deserialization model for WinUIGallery/SampleSupport/Data/ControlInfoData.json.
+/// This mirrors WinUIGallery.Models.ControlInfoData plus the fields that already exist in
+/// ControlInfoDataSchema.json/ControlInfoData.json but are not (yet) consumed by the running
+/// app (Tags, RelatedControls), and the optional "Catalog" override block added for this
+/// exporter (see ControlInfoCatalogOverride).
+///
+internal sealed class ControlInfoRoot
+{
+ public List Groups { get; set; } = [];
+}
+
+internal sealed class ControlInfoGroup
+{
+ public string UniqueId { get; set; } = string.Empty;
+ public string Title { get; set; } = string.Empty;
+ public bool IsSpecialSection { get; set; }
+ public List Items { get; set; } = [];
+}
+
+internal sealed class ControlInfoItem
+{
+ public string UniqueId { get; set; } = string.Empty;
+ public string Title { get; set; } = string.Empty;
+ public string[] BaseClasses { get; set; } = [];
+ public string[] Tags { get; set; } = [];
+ public string ApiNamespace { get; set; } = string.Empty;
+ public string Subtitle { get; set; } = string.Empty;
+ public string Description { get; set; } = string.Empty;
+ public bool IsNew { get; set; }
+ public bool IsUpdated { get; set; }
+ public bool IsPreview { get; set; }
+ public List Docs { get; set; } = [];
+
+ ///
+ /// UniqueIds of other items in this same file that are conceptually related. Already present
+ /// in ControlInfoData.json/ControlInfoDataSchema.json but not consumed by the app today.
+ ///
+ public string[] RelatedControls { get; set; } = [];
+
+ ///
+ /// Optional, catalog-only overrides. Everything here is additive/derivable metadata that is
+ /// not needed by the running gallery app itself, so it is only ever read by the exporter.
+ ///
+ public ControlInfoCatalogOverride? Catalog { get; set; }
+}
+
+internal sealed class ControlInfoDocLink
+{
+ public string Title { get; set; } = string.Empty;
+ public string Uri { get; set; } = string.Empty;
+}
+
+///
+/// Explicit, opt-in override mechanism for the exported catalog manifest. Every field is
+/// optional and additive: omitting "Catalog" entirely (the overwhelming majority of items)
+/// produces a fully-populated catalog entry derived from the existing fields above plus the
+/// on-disk sample folder. Use this block only for the rare item that needs to diverge from what
+/// can be safely derived automatically.
+///
+internal sealed class ControlInfoCatalogOverride
+{
+ ///
+ /// When true, this item is left out of the generated catalog manifest entirely (for example,
+ /// a page that is a developer utility rather than a genuine, documentable sample).
+ ///
+ public bool Exclude { get; set; }
+
+ ///
+ /// Additional search aliases that are useful for an external catalog/agent but too broad or
+ /// noisy for the in-app search experience (which already uses Tags).
+ ///
+ public string[] Aliases { get; set; } = [];
+
+ ///
+ /// Extra related-sample references that point outside this repository, formatted as
+ /// "{owner}/{repo}#{uniqueId}". Used to extend (not replace) RelatedControls, which can only
+ /// reference other items in this same file.
+ ///
+ public string[] RelatedSamples { get; set; } = [];
+}
diff --git a/tools/CatalogExporter/SubstitutionResolver.cs b/tools/CatalogExporter/SubstitutionResolver.cs
new file mode 100644
index 000000000..d4350267e
--- /dev/null
+++ b/tools/CatalogExporter/SubstitutionResolver.cs
@@ -0,0 +1,356 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml.Linq;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Resolves the $(Token) placeholders that snippet bundles contain.
+///
+///
+///
+/// A sample page can pair a snippet with a set of ControlExampleSubstitution entries, each
+/// binding a token to a live option control:
+///
+/// <controls:ControlExampleSubstitution Key="Spacing" Value="{x:Bind SpacingSlider.Value, Mode=OneWay}" />
+///
+/// In the running app the token is replaced as the user moves the slider, so a reader never sees
+/// the raw $(Spacing). Published verbatim, though, that same snippet is not valid XAML and
+/// cannot be pasted into a project.
+///
+///
+/// This resolver substitutes the value the control starts with, which is exactly what the gallery
+/// renders when the page first loads. It is deliberately conservative: a token is replaced only
+/// when the initial value can be read directly out of the markup. Anything that depends on running
+/// code - converter functions such as BoolToLowerString(x.IsOn), or a control that never
+/// declares an initial value - is left as the original token rather than guessed at, because
+/// publishing a value the gallery does not actually show would be worse than publishing none.
+///
+///
+internal static class SubstitutionResolver
+{
+ private static readonly XNamespace XamlNamespace = "http://schemas.microsoft.com/winfx/2006/xaml";
+
+ /// Matches ((SomeType)elementName.SelectedItem).Member.
+ private static readonly Regex CastedSelectionRegex = new(
+ @"^\(\([^)]+\)(?[A-Za-z_][\w]*)\.(?[A-Za-z_][\w]*)\)\.(?[A-Za-z_][\w]*)$",
+ RegexOptions.Compiled);
+
+ ///
+ /// Builds the token map for one ControlExample. Keys are token names without the
+ /// $( ) wrapper; only confidently resolved tokens are present.
+ ///
+ public static Dictionary BuildMap(XElement controlExample, XElement pageRoot)
+ {
+ Dictionary map = new(StringComparer.Ordinal);
+
+ XElement? container = controlExample
+ .Elements()
+ .FirstOrDefault(e => e.Name.LocalName == "ControlExample.Substitutions");
+
+ if (container is null)
+ {
+ return map;
+ }
+
+ foreach (XElement substitution in container.Elements().Where(e => e.Name.LocalName == "ControlExampleSubstitution"))
+ {
+ string? key = (string?)substitution.Attribute("Key");
+ string? value = (string?)substitution.Attribute("Value");
+ if (string.IsNullOrEmpty(key) || value is null)
+ {
+ continue;
+ }
+
+ // A disabled substitution renders as the empty string, not as its value, so the
+ // condition has to be settled before the value matters. When it cannot be settled the
+ // token is left alone: guessing wrong would either invent markup the gallery omits or
+ // drop markup it shows.
+ bool? enabled = ResolveIsEnabled(substitution, pageRoot);
+ if (enabled is null)
+ {
+ continue;
+ }
+
+ if (enabled == false)
+ {
+ map[key] = string.Empty;
+ continue;
+ }
+
+ string? resolved = ResolveValue(value, pageRoot);
+ if (resolved is not null)
+ {
+ map[key] = resolved;
+ }
+ }
+
+ return map;
+ }
+
+ ///
+ /// Evaluates a substitution's IsEnabled condition. Absent means enabled; null means the
+ /// condition depends on state this exporter cannot read.
+ ///
+ private static bool? ResolveIsEnabled(XElement substitution, XElement pageRoot)
+ {
+ string? raw = (string?)substitution.Attribute("IsEnabled");
+ if (raw is null)
+ {
+ return true;
+ }
+
+ string? resolved = ResolveValue(raw, pageRoot);
+ if (bool.TryParse(resolved?.Trim(), out bool enabled))
+ {
+ return enabled;
+ }
+
+ return ResolveUnsetBooleanDefault(raw, pageRoot);
+ }
+
+ ///
+ /// Boolean properties whose documented default is false, so markup that never sets one is
+ /// showing it as false rather than leaving it unknown.
+ ///
+ /// The list is explicit because the opposite case is common enough to matter: IsEnabled,
+ /// IsTabStop and IsHitTestVisible all default to true, so a blanket "unset means false" rule
+ /// would invert them.
+ ///
+ private static readonly HashSet DefaultFalseBooleans = new(StringComparer.Ordinal)
+ {
+ "IsChecked", "IsOn", "IsSticky", "IsOpen",
+ };
+
+ ///
+ /// Resolves a gate like {x:Bind DisableButton.IsChecked.Value} against a CheckBox that
+ /// never sets IsChecked. The control starts unchecked, so the gallery renders that
+ /// substitution as an empty string on load — and because these gates typically supply a whole
+ /// attribute, leaving the token in place produces XAML that is not well-formed and gets
+ /// discarded downstream. Resolving it is therefore both more accurate and what keeps the
+ /// sample publishable.
+ ///
+ private static bool? ResolveUnsetBooleanDefault(string binding, XElement pageRoot)
+ {
+ string trimmed = binding.Trim();
+ if (!trimmed.StartsWith("{x:Bind", StringComparison.Ordinal) || !trimmed.EndsWith('}'))
+ {
+ return null;
+ }
+
+ string body = trimmed[7..^1].Trim();
+ int comma = body.IndexOf(',');
+ string path = (comma < 0 ? body : body[..comma]).Trim();
+
+ // A converter or cast depends on code this exporter does not run.
+ if (path.Contains('(') || path.Contains(')'))
+ {
+ return null;
+ }
+
+ string[] segments = path.Split('.');
+ if (segments.Length is < 2 or > 3)
+ {
+ return null;
+ }
+
+ // A nullable bool reads as IsChecked.Value in x:Bind but is still the IsChecked attribute.
+ if (segments.Length == 3 && segments[2] != "Value")
+ {
+ return null;
+ }
+
+ if (!DefaultFalseBooleans.Contains(segments[1]))
+ {
+ return null;
+ }
+
+ XElement? target = FindNamedElement(pageRoot, segments[0]);
+ if (target is null)
+ {
+ return null;
+ }
+
+ // Only an absent attribute means "left at its default". An attribute that is present but
+ // did not resolve above is a binding of its own, and stays unknown.
+ return target.Attribute(segments[1]) is null ? false : null;
+ }
+
+ ///
+ /// Replaces every $(Token) in that appears in
+ /// . Tokens with no entry are left exactly as they were.
+ ///
+ public static string Apply(string text, IReadOnlyDictionary map)
+ {
+ if (map.Count == 0 || string.IsNullOrEmpty(text))
+ {
+ return text;
+ }
+
+ StringBuilder result = new(text.Length);
+ int index = 0;
+
+ while (index < text.Length)
+ {
+ int start = text.IndexOf("$(", index, StringComparison.Ordinal);
+ if (start < 0)
+ {
+ result.Append(text, index, text.Length - index);
+ break;
+ }
+
+ int end = text.IndexOf(')', start + 2);
+ if (end < 0)
+ {
+ result.Append(text, index, text.Length - index);
+ break;
+ }
+
+ string token = text[(start + 2)..end];
+ result.Append(text, index, start - index);
+ result.Append(map.TryGetValue(token, out string? replacement) ? replacement : text[start..(end + 1)]);
+ index = end + 1;
+ }
+
+ return result.ToString();
+ }
+
+ ///
+ /// Turns a substitution's Value into a literal, or returns null when it cannot be
+ /// determined without running the app.
+ ///
+ private static string? ResolveValue(string value, XElement pageRoot)
+ {
+ // A plain literal needs no lookup. Its surrounding whitespace is significant: several
+ // snippets rely on a value like ' IsSticky="True" ' supplying its own separating spaces.
+ string trimmed = value.Trim();
+ if (!trimmed.StartsWith('{'))
+ {
+ return value;
+ }
+
+ if (!trimmed.StartsWith("{x:Bind", StringComparison.Ordinal) || !trimmed.EndsWith('}'))
+ {
+ return null;
+ }
+
+ string body = trimmed[7..^1].Trim();
+ int comma = body.IndexOf(',');
+ string path = (comma < 0 ? body : body[..comma]).Trim();
+
+ // A cast around a selector, ((ComboBoxItem)combo.SelectedItem).Content, is still just a
+ // selection lookup once the cast is stripped, so it resolves like any other.
+ Match cast = CastedSelectionRegex.Match(path);
+ if (cast.Success)
+ {
+ XElement? selector = FindNamedElement(pageRoot, cast.Groups["element"].Value);
+ XElement? item = selector is null ? null : FindSelectedItem(selector);
+ if (item is null)
+ {
+ return null;
+ }
+
+ string member = cast.Groups["member"].Value;
+ return member == "Content" ? ReadItemContent(item) : (string?)item.Attribute(member);
+ }
+
+ // Converter functions - BoolToLowerString(x.IsOn) - depend on code this exporter does not run.
+ if (path.Contains('(') || path.Contains(')'))
+ {
+ return null;
+ }
+
+ string[] segments = path.Split('.');
+ if (segments.Length < 2)
+ {
+ return null;
+ }
+
+ XElement? target = FindNamedElement(pageRoot, segments[0]);
+ if (target is null)
+ {
+ return null;
+ }
+
+ return ResolveProperty(target, segments[1..]);
+ }
+
+ private static string? ResolveProperty(XElement target, string[] propertyPath)
+ {
+ string property = propertyPath[0];
+
+ // A nullable bool reads as IsChecked.Value in x:Bind but is still the IsChecked attribute.
+ if (propertyPath.Length == 2 && propertyPath[1] == "Value")
+ {
+ return (string?)target.Attribute(property);
+ }
+
+ if (propertyPath.Length > 1)
+ {
+ // Sub-properties such as BorderThickness.Top would need XAML type conversion to split
+ // reliably, so they are left unresolved.
+ return null;
+ }
+
+ if (property is "SelectedItem" or "SelectedValue")
+ {
+ return ResolveSelectedItem(target);
+ }
+
+ return (string?)target.Attribute(property);
+ }
+
+ ///
+ /// Finds the initially selected item of a selector and returns its displayed text. Requires an
+ /// explicit selection: a selector that declares none starts empty, and assuming the first item
+ /// would publish something the gallery does not show.
+ ///
+ private static string? ResolveSelectedItem(XElement selector)
+ {
+ XElement? selected = FindSelectedItem(selector);
+ return selected is null ? null : ReadItemContent(selected);
+ }
+
+ private static XElement? FindSelectedItem(XElement selector)
+ {
+ List items = selector
+ .Elements()
+ .Where(e => !e.Name.LocalName.Contains('.'))
+ .ToList();
+
+ XElement? selected = items.FirstOrDefault(e => string.Equals((string?)e.Attribute("IsSelected"), "True", StringComparison.OrdinalIgnoreCase));
+ if (selected is not null)
+ {
+ return selected;
+ }
+
+ string? selectedIndex = (string?)selector.Attribute("SelectedIndex");
+ if (!int.TryParse(selectedIndex, out int index) || index < 0 || index >= items.Count)
+ {
+ return null;
+ }
+
+ return items[index];
+ }
+
+ private static string? ReadItemContent(XElement item)
+ {
+ string? content = (string?)item.Attribute("Content");
+ if (!string.IsNullOrEmpty(content))
+ {
+ return content;
+ }
+
+ // Text puts the content in the element body instead.
+ return item.HasElements ? null : NullIfWhiteSpace(item.Value.Trim());
+ }
+
+ private static XElement? FindNamedElement(XElement root, string name) =>
+ root.Descendants().FirstOrDefault(e =>
+ (string?)e.Attribute(XamlNamespace + "Name") == name || (string?)e.Attribute("Name") == name);
+
+ private static string? NullIfWhiteSpace(string value) => string.IsNullOrWhiteSpace(value) ? null : value;
+}
diff --git a/tools/CatalogExporter/TokenFallback.cs b/tools/CatalogExporter/TokenFallback.cs
new file mode 100644
index 000000000..cc766d647
--- /dev/null
+++ b/tools/CatalogExporter/TokenFallback.cs
@@ -0,0 +1,306 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// The last step between a snippet and the index: removes any $(Token) that
+/// could not resolve.
+///
+///
+///
+/// The resolver is deliberately conservative and leaves a token alone rather than guess at it. That
+/// is the right call for accuracy, but a published token is not something a consumer can paste: it
+/// is not a valid value for the property it sits on, and an agent reading the index has no way to
+/// know it is a placeholder rather than literal text.
+///
+///
+/// So whatever survives resolution is deleted here, by removing the smallest construct that keeps
+/// the fragment valid: the enclosing attribute when the token sits in one, otherwise just the token
+/// text. Deleting an attribute is a safe degradation because the property then falls back to its own
+/// default - which is exactly what the gallery itself is showing whenever the token was unresolvable
+/// for the usual reason, namely that the option control it binds to was never given an initial value.
+///
+///
+/// This is intentionally a fallback and not a resolution strategy. It runs only on what the resolver
+/// declined to settle, and it is what lets the exporter guarantee that no published XAML contains a
+/// placeholder, without having to infer a value it cannot actually know.
+///
+///
+internal static partial class TokenFallback
+{
+ ///
+ /// Marks a deletion point so the line-level cleanup can tell a line that a removal emptied from
+ /// one that was already blank. A private-use code point, so it cannot collide with snippet text.
+ ///
+ private const char Marker = '\uE000';
+
+ /// True when still contains a $(Token) placeholder.
+ public static bool ContainsToken(string? text) => text is not null && TokenRegex().IsMatch(text);
+
+ /// Token names still present in , in order of first appearance.
+ public static List TokenNames(string text)
+ {
+ List names = [];
+ foreach (Match match in TokenRegex().Matches(text))
+ {
+ string name = match.Groups["name"].Value;
+ if (!names.Contains(name, StringComparer.Ordinal))
+ {
+ names.Add(name);
+ }
+ }
+
+ return names;
+ }
+
+ ///
+ /// Removes every unresolved token from a XAML fragment, deleting the attribute that contains it
+ /// when there is one. A fragment with no tokens is returned unchanged.
+ ///
+ public static string StripFromXaml(string xaml)
+ {
+ if (!ContainsToken(xaml))
+ {
+ return xaml;
+ }
+
+ return ApplyRemovals(xaml, CollectXamlRemovals(xaml));
+ }
+
+ ///
+ /// Walks the fragment and records what to delete for each token: the whole attribute when the
+ /// token is inside an attribute value, otherwise the token text on its own.
+ ///
+ private static List<(int Start, int Length)> CollectXamlRemovals(string xaml)
+ {
+ List<(int Start, int Length)> removals = [];
+ int index = 0;
+
+ while (index < xaml.Length)
+ {
+ if (StartsWith(xaml, index, "", index + 4, StringComparison.Ordinal);
+ int commentEnd = close < 0 ? xaml.Length : close + 3;
+
+ // A token inside a comment breaks nothing, but leaving it would still publish a
+ // placeholder, so the token text goes and the surrounding prose stays.
+ AddTokenRemovals(xaml, index, commentEnd, removals);
+ index = commentEnd;
+ continue;
+ }
+
+ if (xaml[index] == '<')
+ {
+ index = ScanTag(xaml, index, removals);
+ continue;
+ }
+
+ int nextTag = xaml.IndexOf('<', index);
+ int textEnd = nextTag < 0 ? xaml.Length : nextTag;
+ AddTokenRemovals(xaml, index, textEnd, removals);
+ index = textEnd;
+ }
+
+ return removals;
+ }
+
+ ///
+ /// Scans one tag, recording a removal for each attribute whose value contains a token, and
+ /// returns the index just past the tag.
+ ///
+ private static int ScanTag(string xaml, int tagStart, List<(int Start, int Length)> removals)
+ {
+ int index = tagStart + 1;
+
+ // The element name, which cannot contain an attribute and so is skipped wholesale.
+ while (index < xaml.Length && xaml[index] != '>' && !char.IsWhiteSpace(xaml[index]))
+ {
+ index++;
+ }
+
+ while (index < xaml.Length && xaml[index] != '>')
+ {
+ if (char.IsWhiteSpace(xaml[index]) || xaml[index] == '/')
+ {
+ index++;
+ continue;
+ }
+
+ int nameStart = index;
+ while (index < xaml.Length && xaml[index] != '=' && xaml[index] != '>' && xaml[index] != '/' && !char.IsWhiteSpace(xaml[index]))
+ {
+ index++;
+ }
+
+ int cursor = SkipWhiteSpace(xaml, index);
+ if (cursor >= xaml.Length || xaml[cursor] != '=')
+ {
+ // Not "name=value". A token standing where an attribute name belongs is a
+ // substitution that expands to whole attributes, so the token itself is the smallest
+ // construct that can be deleted. Left in place it is not even well-formed XML.
+ if (xaml.AsSpan(nameStart, index - nameStart).Contains("$(", StringComparison.Ordinal))
+ {
+ AddRemoval(xaml, nameStart, index, removals);
+ }
+
+ index = cursor;
+ continue;
+ }
+
+ cursor = SkipWhiteSpace(xaml, cursor + 1);
+ if (cursor >= xaml.Length || (xaml[cursor] != '"' && xaml[cursor] != '\''))
+ {
+ index = cursor;
+ continue;
+ }
+
+ char quote = xaml[cursor];
+ int valueStart = cursor + 1;
+ int valueEnd = xaml.IndexOf(quote, valueStart);
+ if (valueEnd < 0)
+ {
+ // Unterminated attribute: the fragment is malformed and is rejected elsewhere.
+ return xaml.Length;
+ }
+
+ if (xaml.AsSpan(valueStart, valueEnd - valueStart).Contains("$(", StringComparison.Ordinal))
+ {
+ AddRemoval(xaml, nameStart, valueEnd + 1, removals);
+ }
+
+ index = valueEnd + 1;
+ }
+
+ return index < xaml.Length ? index + 1 : xaml.Length;
+ }
+
+ ///
+ /// Records the removal of the span [, ) along with
+ /// the whitespace in front of it.
+ ///
+ private static void AddRemoval(string xaml, int start, int end, List<(int Start, int Length)> removals)
+ {
+ // The whitespace separating this attribute from whatever precedes it goes with it, newlines
+ // included. Taking it from the front rather than the back is what keeps the result tidy: an
+ // attribute written on its own line takes that line with it, and the last attribute in a tag
+ // does not leave the closing "/>" stranded.
+ while (start > 0 && char.IsWhiteSpace(xaml[start - 1]))
+ {
+ start--;
+ }
+
+ removals.Add((start, end - start));
+ }
+
+ /// Records a removal for each token in between two offsets.
+ private static void AddTokenRemovals(string text, int start, int end, List<(int Start, int Length)> removals)
+ {
+ foreach (Match match in TokenRegex().Matches(text[start..end]))
+ {
+ removals.Add((start + match.Index, match.Length));
+ }
+ }
+
+ private static int SkipWhiteSpace(string text, int index)
+ {
+ while (index < text.Length && char.IsWhiteSpace(text[index]))
+ {
+ index++;
+ }
+
+ return index;
+ }
+
+ private static bool StartsWith(string text, int index, string value) =>
+ index + value.Length <= text.Length && text.AsSpan(index, value.Length).SequenceEqual(value);
+
+ ///
+ /// Cuts the recorded spans out of and tidies the result: a line that a
+ /// removal emptied is dropped rather than left as whitespace, and a line a removal shortened
+ /// loses any trailing whitespace it gained.
+ ///
+ private static string ApplyRemovals(string text, List<(int Start, int Length)> removals)
+ {
+ if (removals.Count == 0)
+ {
+ return text;
+ }
+
+ removals.Sort(static (left, right) => left.Start.CompareTo(right.Start));
+
+ StringBuilder builder = new(text.Length);
+ int index = 0;
+
+ foreach ((int start, int length) in removals)
+ {
+ // Two tokens in one attribute value produce two removals covering the same span.
+ if (start < index)
+ {
+ continue;
+ }
+
+ builder.Append(text, index, start - index);
+ builder.Append(Marker);
+ index = start + length;
+ }
+
+ builder.Append(text, index, text.Length - index);
+ return CleanLines(builder.ToString());
+ }
+
+ private static string CleanLines(string text)
+ {
+ List kept = [];
+
+ foreach (string line in text.Split('\n'))
+ {
+ if (!line.Contains(Marker))
+ {
+ kept.Add(line);
+ continue;
+ }
+
+ string cleaned = line.Replace(Marker.ToString(), string.Empty);
+
+ // The line held nothing but the removed attribute, so the blank it left goes too.
+ if (cleaned.Trim().Length == 0)
+ {
+ continue;
+ }
+
+ kept.Add(TrimTrailingSpaces(cleaned));
+ }
+
+ return string.Join('\n', kept);
+ }
+
+ ///
+ /// Trims spaces and tabs from the end of a line, leaving any carriage return in place so that
+ /// CRLF snippets keep their line endings.
+ ///
+ private static string TrimTrailingSpaces(string line)
+ {
+ int end = line.Length;
+ bool carriageReturn = end > 0 && line[end - 1] == '\r';
+ if (carriageReturn)
+ {
+ end--;
+ }
+
+ while (end > 0 && (line[end - 1] == ' ' || line[end - 1] == '\t'))
+ {
+ end--;
+ }
+
+ return line[..end] + (carriageReturn ? "\r" : string.Empty);
+ }
+
+ /// A $(Token) placeholder, capturing the token name.
+ [GeneratedRegex(@"\$\((?[^)]*)\)")]
+ private static partial Regex TokenRegex();
+}
diff --git a/tools/CatalogExporter/XamlFragment.cs b/tools/CatalogExporter/XamlFragment.cs
new file mode 100644
index 000000000..707728a5b
--- /dev/null
+++ b/tools/CatalogExporter/XamlFragment.cs
@@ -0,0 +1,208 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace WinUIGallery.CatalogExporter;
+
+///
+/// Structural checks on a snippet's XAML, plus the namespace declarations a consumer needs to
+/// paste it somewhere else.
+///
+internal static partial class XamlFragment
+{
+ ///
+ /// Prefixes a consumer's page already declares (or that exist only at design time), so
+ /// emitting them as required imports would be noise at best and a duplicate attribute at
+ /// worst.
+ ///
+ private static readonly HashSet IgnoredPrefixes = new(StringComparer.Ordinal)
+ {
+ "x", "d", "mc", "xml", "xmlns",
+
+ // Not a prefix at all: "using" is the scheme half of a XAML namespace URI, as in
+ // xmlns:sys="using:System". The type-reference branch of BindingPrefixRegex cannot tell
+ // that apart from a real "prefix:Type" reference, and no consumer ever needs an import
+ // for it.
+ "using",
+ };
+
+ ///
+ /// True when parses as a well-formed XML fragment.
+ ///
+ /// This mirrors winappCli's ScenarioSanitizer.XamlIsWellFormed, including its trick of
+ /// synthesizing a declaration for every prefix it sees, so that a snippet using an undeclared
+ /// prefix is not treated as broken. Matching the consumer's check matters more than being
+ /// stricter than it: anything this accepts but the consumer rejects would be published and
+ /// then silently discarded on the other side.
+ ///
+ public static bool IsWellFormed(string xaml)
+ {
+ HashSet prefixes = new(StringComparer.Ordinal);
+ foreach (Match match in AnyPrefixRegex().Matches(xaml))
+ {
+ string prefix = match.Groups[1].Value;
+
+ // xml and xmlns are reserved and cannot be (re)declared.
+ if (prefix is "xml" or "xmlns")
+ {
+ continue;
+ }
+
+ prefixes.Add(prefix);
+ }
+
+ StringBuilder wrapped = new("').Append(xaml).Append("");
+
+ XmlReaderSettings settings = new()
+ {
+ DtdProcessing = DtdProcessing.Prohibit,
+ XmlResolver = null,
+ };
+
+ try
+ {
+ using XmlReader reader = XmlReader.Create(new StringReader(wrapped.ToString()), settings);
+ while (reader.Read())
+ {
+ }
+
+ return true;
+ }
+ catch (XmlException)
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Collects the xmlns declarations on a page's root element, keyed by prefix.
+ ///
+ public static Dictionary ReadPageDeclarations(XElement pageRoot)
+ {
+ Dictionary declarations = new(StringComparer.Ordinal);
+ foreach (XAttribute attribute in pageRoot.Attributes().Where(a => a.IsNamespaceDeclaration))
+ {
+ // The default xmlns has an empty local prefix and needs no import: a consumer pasting
+ // into an existing page already has it.
+ if (attribute.Name.NamespaceName.Length == 0)
+ {
+ continue;
+ }
+
+ declarations[attribute.Name.LocalName] = attribute.Value;
+ }
+
+ return declarations;
+ }
+
+ ///
+ /// Returns the full xmlns declarations needs, resolved against the
+ /// declarations on its own page. Only prefixes the snippet actually uses are returned, so a
+ /// consumer is not told to add namespaces for controls that never appear in it.
+ ///
+ /// A prefix the page does not declare is skipped rather than guessed at: inventing a URI would
+ /// produce an import that looks authoritative and does not compile.
+ ///
+ public static List DetectImports(string xaml, IReadOnlyDictionary pageDeclarations)
+ {
+ SortedSet imports = new(StringComparer.Ordinal);
+
+ foreach (string prefix in UsedPrefixes(xaml))
+ {
+ if (pageDeclarations.TryGetValue(prefix, out string? uri))
+ {
+ imports.Add($"xmlns:{prefix}=\"{uri}\"");
+ }
+ }
+
+ return [.. imports];
+ }
+
+ ///
+ /// Prefixes binds to that its own page never declares, so no import
+ /// can be published for them.
+ ///
+ /// cannot surface these, by design: it synthesizes a declaration for
+ /// every prefix it sees so that it agrees with the consumer's parser. The fragment therefore
+ /// parses on both sides and fails only when someone pastes it alongside the imports this index
+ /// published — which are necessarily missing the one it actually needed.
+ ///
+ public static List UnresolvedPrefixes(string xaml, IReadOnlyDictionary pageDeclarations)
+ {
+ // A snippet that declares a prefix on its own root carries the binding with it, so it needs
+ // nothing from the page and nothing published alongside it.
+ HashSet selfDeclared = new(StringComparer.Ordinal);
+ foreach (Match match in SelfDeclaredPrefixRegex().Matches(xaml))
+ {
+ selfDeclared.Add(match.Groups[1].Value);
+ }
+
+ SortedSet unresolved = new(StringComparer.Ordinal);
+
+ foreach (string prefix in UsedPrefixes(xaml))
+ {
+ if (!pageDeclarations.ContainsKey(prefix) && !selfDeclared.Contains(prefix))
+ {
+ unresolved.Add(prefix);
+ }
+ }
+
+ return [.. unresolved];
+ }
+
+ ///
+ /// Prefixes used in a way that actually binds to a namespace: an element name, an attribute
+ /// name, a markup extension, or a type reference in an attribute value.
+ ///
+ /// This is deliberately narrower than the regex used by , which
+ /// over-collects on purpose. Here, matching something like the "https" in a URL would emit a
+ /// bogus import, so only the positions where XAML resolves a prefix are considered.
+ ///
+ private static IEnumerable UsedPrefixes(string xaml)
+ {
+ HashSet prefixes = new(StringComparer.Ordinal);
+
+ foreach (Match match in BindingPrefixRegex().Matches(xaml))
+ {
+ for (int group = 1; group < match.Groups.Count; group++)
+ {
+ string prefix = match.Groups[group].Value;
+ if (prefix.Length > 0 && !IgnoredPrefixes.Contains(prefix))
+ {
+ prefixes.Add(prefix);
+ }
+ }
+ }
+
+ return prefixes;
+ }
+
+ /// Any "prefix:" occurrence — matches winappCli's namespace-synthesis regex.
+ [GeneratedRegex(@"([A-Za-z_][\w.\-]*):")]
+ private static partial Regex AnyPrefixRegex();
+
+ /// A prefix the fragment declares itself, as in <StackPanel xmlns:sys="using:System">.
+ [GeneratedRegex(@"xmlns:([A-Za-z_][\w.\-]*)\s*=")]
+ private static partial Regex SelfDeclaredPrefixRegex();
+
+ ///
+ /// Prefix positions XAML actually resolves: element names (<p:Foo, </p:Foo),
+ /// attribute names (p:Foo=), markup extensions ({p:Foo}) and type references ("p:Foo").
+ ///
+ /// The attribute-name branch stops before the "=" rather than consuming it, so an attribute
+ /// that is itself prefixed does not hide a prefixed type in its value: in
+ /// x:DataType="local:Contact" both "x" and "local" have to be found.
+ ///
+ [GeneratedRegex(@"?([A-Za-z_][\w.\-]*):[A-Za-z_]|\s([A-Za-z_][\w.\-]*):[A-Za-z_][\w.\-]*(?=\s*=)|\{\s*([A-Za-z_][\w.\-]*):[A-Za-z_]|=""\s*([A-Za-z_][\w.\-]*):[A-Za-z_]")]
+ private static partial Regex BindingPrefixRegex();
+}