API
ComboBox
-
Important attributes:
Items
orItemsSource
specify the collection (preferablyIObservableCollection
to support event handling on value changes) to be used to populate the control.SelectedItem
defines the element that appears selected by the control by default. If not defined, no element will be selected.DisplayMemberPath
defines the name of the property to be used to display each individual choice.
<ComboBox ItemsSource="{x:Bind Items}" SelectedItem="{x:Bind Items[0]}" DisplayMemberPath="Display" />
CommandBar
-
CommandBar is a lightweight control that can organize a bar of buttons.
<CommandBar> <AppBarButton x:Name="AddCustomer" Click="AddCustomer_Click" Label="Add"> <SymbolIcon Symbol="AddFriend"/> </AppBarButton> <AppBarButton x:Name="DeleteCustomer" Click="DeleteCustomer_Click" Label="Delete"> <SymbolIcon Symbol="Delete"/> </AppBarButton> <AppBarButton x:Name="btn_MoveSideBar" Click="btn_MoveSideBar_Click" Label="Move sidebar"> <SymbolIcon x:Name="btn_MoveSideBar_Symbol" Symbol="AlignRight"/> </AppBarButton> </CommandBar>
DataGrid
Dialog boxes
In XAML, the MessageDialog object can be used to create a modal dialog box (i.e. one that does not allow interaction with the main window until the dialog box has been cleared).
The MessageDialog object can take a string argument containing the text of the dialog box.
It is actually displayed by calling the object's ShowAsync() method.
Because this is an asynchronous call, it must be await
ed, which requires the System
namespace. (src)
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.UI.Popups;
using System;
namespace WiredBrainCoffee.UWP
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void AddCustomer(object sender, RoutedEventArgs e)
{
var messageDialog = new MessageDialog("Customer added!");
await messageDialog.ShowAsync();
}
}
}
Grid
-
The
Grid
layout panel is analogous to the grid geometry manager in tkinter. However, in XAML you are forced to explicitly declare RowDefinition** and **
ColumnDefinition elements. Whereas in tkinter, the widget being placed declares its own grid position. If the grid is sparse, the empty rows and columns appear to be ignored.Grid star-sizing works similar to
flex-grow
andflex-shrink
CSS style statements used with Flexbox.<Grid> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Rectangle Fill="LightGray"/> <Rectangle Fill="LightSteelBlue" Grid.Row="1"/> <Rectangle Fill="LightBlue" Grid.Row="2"/> <Rectangle Fill="LightCyan" Grid.Row="3"/> <Rectangle Fill="LightSeaGreen" Grid.Row="4"/> <Rectangle Fill="LightGreen" Grid.Row="5"/> <Rectangle Fill="LightGoldenrodYellow" Grid.Row="6" /> <Rectangle Fill="LightSalmon" Grid.Row="7"/> <Rectangle Fill="LightCoral" Grid.Row="8"/> </Grid>
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Rectangle Fill="LightGray"/> <Rectangle Fill="LightSteelBlue" Grid.Column="1"/> <Rectangle Fill="LightBlue" Grid.Column="2"/> <Rectangle Fill="LightCyan" Grid.Column="3"/> <Rectangle Fill="LightSeaGreen" Grid.Column="4"/> <Rectangle Fill="LightGreen" Grid.Column="5"/> <Rectangle Fill="LightGoldenrodYellow" Grid.Column="6" /> <Rectangle Fill="LightSalmon" Grid.Column="7"/> <Rectangle Fill="LightCoral" Grid.Column="8"/> </Grid>
ListDetailsView
-
ListDetailsView is a custom control available from the Windows Community Toolkit (Nuget package
Microsoft.Toolkit.UWP
) that implements the Master/Details pattern.xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls
: namespace- toolkit:ListDetailsView
toolkit:ListDetailsView.
ItemTemplate property-element for how items are rendered in sidebartoolkit:ListDetailsView.
DetailsTemplate property-element for how items are rendered in the main panetoolkit:ListDetailsView.
NoSelectionContentTemplate property-element for how the main pane is rendered with no item selectedtoolkit:ListDetailsView.
AppCommandBar
- toolkit:ListDetailsView
<Page <!-- ... --> xmlns:toolkit="using:Microsoft.Toolkit.Uwp.UI.Controls"> <toolkit:ListDetailsView> <toolkit:ListDetailsView.ItemTemplate> </toolkit:ListDetailsView.ItemTemplate> <toolkit:ListDetailsView.DetailsTemplate> </toolkit:ListDetailsView.DetailsTemplate> <toolkit:ListDetailsView.NoSelectionContentTemplate> </toolkit:ListDetailsView.NoSelectionContentTemplate> <toolkit:ListDetailsView.AppCommandBar> </toolkit:ListDetailsView.AppCommandBar> </toolkit:ListDetailsView> </Page>
ListView
-
<ListView ItemsSource="{x:Bind Items}" SelectedItem="{x:Bind Items[0]}" DisplayMemberPath="Display"/>
Important attributes:
Items
orItemsSource
specify the collection (preferablyIObservableCollection
to support event handling on value changes) to be used to populate the control.SelectedItem
defines the element that appears selected by the control by default. If not defined, no element will be selected.DisplayMemberPath
defines the name of the property to be used to display each individual choice.
<Window x:Class="Scratchpad1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Scratchpad1" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center"> <ComboBox ItemsSource="{x:Bind Items}" SelectedItem="{x:Bind Items[0]}" DisplayMemberPath="Name" /> </StackPanel> </Window>
using System.Collections.Generic; using Microsoft.UI.Xaml; namespace Scratchpad1 { public class Starship { public string Name { get; set; } public string Registry { get; set; } public int Crew { get; set; } public Starship(string name, string registry, int crew) { Name = name; Registry = registry; Crew = crew; } } public sealed partial class MainWindow : Window { //List<string> Items = new List<string>(); Starship[] Items = new Starship[3]; public MainWindow() { this.InitializeComponent(); Items[0]=new Starship("USS Enterprise","NCC-1701",204); Items[1]=new Starship("USS Constitution","NCC-1700",203); Items[2]=new Starship("USS Defiant","NCC-1764",202); } } }
NavigationView
-
NavigationView provides top-level navigation by implementing a collapsible navigation bar ("hamburger menu") that is reactive to window size. It organizes two areas - Pane and Content - into two layout options that differ in the placement of the Pane. The Header content is placed above the Content in both layouts.
It has various display modes that can be specified by setting PaneDisplayMode. By default, PaneDisplayMode is set to Auto, which enables adaptive (i.e. reactive) behavior, switching between Left, LeftCompact, and LeftMinimal display modes depending on window size.
The Pane is the central feature of NavigationView, and it can contain many items organized into several sections.
- MenuItems is the main section containing NavigationView items at the beginning of the control.
- FooterMenuItems is similar but they are added to the end of the control.
- PaneTitle can accept text, which will appear next to the menu button.
- PaneHeader is similar but can accept non-text content.
- PaneFooter can also accept any content.
NavigationView items can be of various types:
- NavigationViewItemHeader can visually organize other navigation items
- NavigationViewItem exposes Content and Icon properties.
- NavigationViewItemSeparator
- AutoSuggestBox
- Settings button visible by default but can be hidden by setting IsSettingsVisible
<Page> <NavigationView> <NavigationView.MenuItems/> </NavigationView> </Page>
Navigation using NavigationView is not automatically implemented but relies on event handling. NavigationView raises an ItemInvoked event when selected, and if the selection has changed then SelectionChanged is also raised.
NavigationView also feature a Back button, which can be disabled or removed by setting IsBackButtonVisible or IsBackEnabled to false. If enabled, this button raises the BackRequested event.
Typical implementations pair NavigationView with a Frame nested within ScrollViewer to support navigating to different views while supporting the back button (see below).
<Page> <Grid> <NavigationView> <ScrollViewer> <Frame x:Name="ContentFrame"/> </ScrollViewer> </NavigationView> </Grid> </Page>
private void Navigation_ItemInvoked(NavigationView sender, NavigationViewItemInvokedArgs args) { ContentFrame.Navigate(typeof(Page1)); }
Page
-
The Page element in UWP is equivalent to
Window
in WPF.Page elements can only accept a single Content sub-element, necessitating the use of a layout panel like Grid, StackPanel, etc.
RelativePanel
-
RelativePanel allows children to declare attributes (e.g.
RelativePanel.RightOf
) to specify position relative to thex:Name
of other children. This is useful in building responsive layouts.Supports several attached properties that allow elements to be aligned with siblings or with the panel itself.
- Panel alignment relations like
AlignLeftWithPanel
,AlignTopWithPanel
,AlignRightWithPanel
,AlignBottomWithPanel
, align controls to the border of the RelativePanel containing them. - Sibling alignment relationships like
AlignLeftWith
,AlignTopWith
,AlignVerticalCenterWith
etc. specify the name of a sibling control to provide alignment. - Sibling positional relations like
LeftOf
,Above
,RightOf
, andBelow
also specify a sibling control.
- Panel alignment relations like
ResourceDictionary
-
Here, Buttons will now be able to be styled using a markup extension
<Button Style="{StaticResource SubmitButton}" Content="Submit"/>
<Application> <Application.Resources> <ResourceDictionary Source="ResourceDictionaries/ButtonDictionary.xaml"/> </Application.Resources> </Application>
<ResourceDictionary> <Style TargetType="Button" x:Key="SubmitButton"> <Setter Property="Background" Value="Green"/> <Setter Property="Padding" Value="5"/> </Style> </ResourceDictionary>
Managing a consistent style will typically necessitate using multiple resource dictionaries. But some elements can only contain a single ResourceDictionary element.
The solution is to place a ResourceDictionary.MergedDictionaries property element within the outermost
ResourceDictionary
. MultipleResourceDictionary
objects can be placed as children of it.<Page> <Page.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Dictionary1.xaml" /> <ResourceDictionary Source="Dictionary2.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Page.Resources> </Page>
Sources
SplitView
-
SplitView can be used to implement hamburger-style navigation. SplitView has two attributes into which controls can be placed,
Pane
andContent
. Pane is not displayed by default. However, by setting the SplitView instance'sIsPaneOpen
attribute to True it can be displayed.The
DisplayMode
attribute controls how the Pane interacts with Content with opened:- Overlay: Pane covers up Content
- Inline: Pane pushes Content to the right.
- CompactInline: Where Pane will fit Pane elements closely, if
CompactPaneLength
is not specified - CompactOverley: Pane's dimensions can be specified using
CompactPaneLength
andOpenPaneLength
StackPanel
-
The StackPanel layout panel in XAML is similar in function to the pack() geometry manager in tkinter, although its default behavior appears to horizontally center elements and stack them vertically.
Notably, StackPanel does not support scroll bars. (src)
TabView
Textbox
-
<Window x:Class="EmployeeManager.WinUI.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EmployeeManager.WinUI" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <TextBox Header="First name"/> </Window>
import tkinter as tk from tkinter.ttk import Entry from tkinter.ttk import LabelFrame win = tk.Tk() frame=LabelFrame(win, text="First name") frame.pack() Entry(frame).pack() tk.mainloop()
VariableSizedWrapGrid
-
VariableSizedWrapGrid can be used to define a field of tiles similar to an HTML flex container (
display: flex;
withflex-wrap: wrap;
). TheOrientation
property is similar to a flex container'sflex-direction
, in that the direction of alignment can be specified.<Page> <VariableSizedWrapGrid Orientation="Horizontal" ItemWidth="100" ItemHeight="100"> <Rectangle Fill="LightGray"/> <Rectangle Fill="LightSteelBlue" /> <Rectangle Fill="LightBlue" /> <Rectangle Fill="LightCyan" /> <Rectangle Fill="LightSeaGreen" /> <Rectangle Fill="LightGreen" /> <Rectangle Fill="LightGoldenrodYellow" /> <Rectangle Fill="LightSalmon" /> <Rectangle Fill="LightCoral" /> <Rectangle Fill="Gray"/> <Rectangle Fill="SteelBlue" /> <Rectangle Fill="CadetBlue" /> <Rectangle Fill="Cyan" /> <Rectangle Fill="SeaGreen" /> <Rectangle Fill="Green" /> <Rectangle Fill="Goldenrod" /> <Rectangle Fill="Salmon" /> <Rectangle Fill="Coral" /> </VariableSizedWrapGrid> </Page>
Notably, the horizontal or vertical alignment of XAML controls is defined on each control, whereas in HTML alignment is specified at the level of the enclosing container.
<TextBlock Content="Hello, world!" HorizontalAlignment="Left" VerticalAlignment="Top"/>
.container p Hello, world!
.container { text-align: right top; }