Skip to content

API

ComboBox

Important attributes:

  • Items or ItemsSource specify the collection (preferably IObservableCollection 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 awaited, 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 and flex-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 sidebar
      • toolkit:ListDetailsView.DetailsTemplate property-element for how items are rendered in the main pane
      • toolkit:ListDetailsView.NoSelectionContentTemplate property-element for how the main pane is rendered with no item selected
      • toolkit:ListDetailsView.AppCommandBar
<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 or ItemsSource specify the collection (preferably IObservableCollection 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 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:

  1. NavigationViewItemHeader can visually organize other navigation items
  2. NavigationViewItem exposes Content and Icon properties.
  3. NavigationViewItemSeparator
  4. AutoSuggestBox
  5. 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 the x: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, and Below also specify a sibling control.

ResourceDictionary

Resource dictionaries

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. Multiple ResourceDictionary 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 and Content. Pane is not displayed by default. However, by setting the SplitView instance's IsPaneOpen 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 and OpenPaneLength

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; with flex-wrap: wrap;). The Orientation property is similar to a flex container's flex-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;
}