WinUI 3 Diagrams

Last updated:

From a XAML File to Objects

Structure

A page's markup, its two partial-class halves, and the objects they create.

How a WinUI page's XAML file becomes a class and a tree of objects MainPage.xaml declares a Page with x:Class MyApp.MainPage containing a StackPanel with a TextBox named SearchBox and a Button whose Click is wired to Search_Click. The build compiles the markup into generated code in the obj folder (MainPage.g.i.cs), the generated half of the partial class MyApp.MainPage, which holds the SearchBox field and the InitializeComponent method. The other half, MainPage.xaml.cs, is the code-behind the developer writes: its constructor calls InitializeComponent, and it defines the Search_Click event handler. At runtime InitializeComponent creates the objects: a MainPage containing a StackPanel, which contains the TextBox referenced by the SearchBox field and the Button whose Click event is wired to the handler. MARKUP MainPage.xaml <Page x:Class="MyApp.MainPage"> <StackPanel> <TextBox x:Name="SearchBox" /> <Button Click="Search_Click" /> </StackPanel> </Page> PARTIAL CLASS MYAPP.MAINPAGE MainPage.g.i.cs [Generated by the build, in obj/] SearchBox field InitializeComponent() MainPage.xaml.cs [Code-behind you write] Constructor calls InitializeComponent() Search_Click event handler OBJECTS AT RUNTIME MainPage StackPanel TextBox SearchBox field Button Click wired the build compiles the markup calls InitializeComponent creates the objects at load

Measure and Arrange

C4 · Dynamic

A panel measures every child, then arranges each one.

The measure and arrange exchange between a StackPanel and its children A vertical StackPanel, the parent panel, offers its width and unlimited height. In the measure pass it calls Measure on the TextBlock (step 1), which reports its DesiredSize (step 2), then does the same for the Button (steps 3 and 4). Only after both are measured does the arrange pass call Arrange on the TextBlock (step 5) and the Button (step 6), giving each its layout slot, the final rectangle it occupies. Each child measures its own children, if it has any, before reporting. StackPanel [Parent panel] offers its width and unlimited height TextBlock needs the size of its text Button needs its label plus padding 1 Measure(available size) 2 DesiredSize 5 Arrange(layout slot) 3 Measure(available size) 4 DesiredSize 6 Arrange(layout slot) measure pass, down result, back up arrange pass, after all measuring

An Element in Its Layout Slot

Structure

Margin, border, padding, and content inside the slot a parent assigns.

Margin, border, padding, and content inside an element's layout slot The layout slot is the rectangle the parent's Arrange call gives the element. The element's margin sits just inside the slot and is outside the element itself, so it is not counted in ActualWidth. Inside the margin is the element's border, then its padding, then its content. With HorizontalAlignment Left and VerticalAlignment Center, the element sits at the left of the slot, centered vertically, and the rest of the slot is unused. LAYOUT SLOT FROM THE PARENT margin padding Content Layout slot the rectangle Arrange gives the element Margin outside the element, not in ActualWidth Border and padding inside the element, around its content Unused slot space HorizontalAlignment Left, VerticalAlignment Center

A List in a StackPanel vs a Star Row

Structure

The same ListView given unlimited height and given a finite row.

A ListView inside a vertical StackPanel compared with one in a star-sized Grid row On the left, a window holds a vertical StackPanel containing a TextBlock and a ListView. The StackPanel offers unlimited height, so the ListView measures itself as tall as all its items, extends past the bottom of the window, and shows no scroll bar. On the right, the same window holds a Grid whose first row is Auto, holding the TextBlock, and whose second row is star-sized, holding the ListView. The Grid gives the ListView the row's finite height, so the list fits inside the window and shows a scroll bar. VERTICAL STACKPANEL window TextBlock ListView Unlimited height: the list runs past the window, no scroll bar GRID: AUTO ROW, THEN STAR ROW window TextBlock Auto row ListView star row The row's height: the list fits and scrolls

Container Recycling in a Virtualized List

C4 · Dynamic

Containers exist only near the viewport and are reused as items scroll.

How a virtualized list reuses item containers while scrolling On the left, a column of data items from a collection of 10,000 orders, showing Order 37 through Order 48. On the right, UI containers exist only for Order 38 through Order 46. Orders 39 to 45 sit inside the viewport, the visible part of the list, and Orders 38 and 46 stand for the buffer just outside it, which in practice holds several viewports' worth of items and is shortened here to one item on each side. Each container is joined by a line to the data item it is bound to. Orders 37, 47, and 48 have no container at all. While the user scrolls down, the container for Order 38 moves out of range, and an arrow shows it being moved to the bottom and rebound to Order 47, joined to it by a dashed line, instead of a new container being created. DATA: 10,000 ORDERS UI CONTAINERS more orders above Order 37 Order 38 Order 39 Order 40 Order 41 Order 42 Order 43 Order 44 Order 45 Order 46 Order 47 Order 48 more orders below Order 38 Order 39 Order 40 Order 41 Order 42 Order 43 Order 44 Order 45 Order 46 rebound to Order 47 viewport recycled no new container while the user scrolls down container in the viewport buffer container (shortened here) data item (only some have UI)

A Frame's Back and Forward Stacks

C4 · Dynamic

How Navigate and GoBack move pages between a frame's two stacks.

How Navigate and GoBack move pages between a Frame's back stack and forward stack Three rows show a Frame's state at three moments, with columns for the back stack, the current page, and the forward stack. In the first row, the back stack holds HomePage, the current page is OrdersPage, and the forward stack is empty. Calling Navigate to DetailPage moves OrdersPage onto the back stack, so the second row shows HomePage and OrdersPage in the back stack, DetailPage as the current page, and an empty forward stack. Calling GoBack then moves DetailPage onto the forward stack and takes OrdersPage off the back stack to become the current page, so the third row shows HomePage in the back stack, OrdersPage current, and DetailPage in the forward stack. BACKSTACK CURRENT PAGE FORWARDSTACK start HomePage OrdersPage empty Navigate( DetailPage) HomePage OrdersPage DetailPage empty GoBack() HomePage OrdersPage DetailPage a page entry moves page shown in the frame history entry (PageStackEntry)

The Parts of a CommandBar

Structure

Content, primary commands, and the overflow menu of an open command bar.

The areas of an open WinUI CommandBar A horizontal command bar shown open. On its left is the content area, holding a text title reading Orders. On its right are the primary commands, three buttons labeled New order, Refresh, and Filters with a separator before Filters, followed by the see more button drawn as an ellipsis. Above the right end of the bar, the overflow menu is open, listing the secondary commands Export and Print. A note says the overflow menu opens upward by default and downward when there isn't room above. A second note says that when the bar narrows, primary commands move into the overflow menu. Export Print OVERFLOW MENU SecondaryCommands Orders New order Refresh Filters ... CONTENT any element, left side PRIMARY COMMANDS AppBarButton, AppBarToggleButton, AppBarSeparator SEE MORE The overflow menu opens upward by default, and downward when there isn't room above. When the bar narrows, primary commands move into the overflow menu, and back out when there's room again.

A Templated Control and Its Templates

Structure

Fixed control logic that finds its parts and states by name.

How a templated control's class connects to its default template and to an app's replacement template On the left, the CopyField control class sets DefaultStyleKey to typeof(CopyField), declares a TemplatePart named CopyButton and TemplateVisualStates named Normal and Copied, and in OnApplyTemplate calls GetTemplateChild("CopyButton"), later calling GoToState("Copied"). On the right are two templates, and one of them is applied. The first is the default style in Themes/Generic.xaml, a Style whose TargetType is local:CopyField, applied when the app sets no template. DefaultStyleKey selects it. The second is an app's own ControlTemplate, set through Template or a Style, which replaces the default. Both templates contain a Button named CopyButton and visual states named Normal and Copied, and the class finds the part and the states by name in whichever template is applied. CONTROL CLASS CopyField.cs [Logic: fixed, ships with the control] DefaultStyleKey = typeof(CopyField) [TemplatePart "CopyButton"] [TemplateVisualState "Normal"] [TemplateVisualState "Copied"] OnApplyTemplate(): GetTemplateChild("CopyButton") On click: GoToState("Copied") TEMPLATES (ONE IS APPLIED) Themes/Generic.xaml [Default style, applied when the app sets no template] <Style TargetType="local:CopyField"> <Button x:Name="CopyButton" /> <VisualState x:Name="Normal" /> <VisualState x:Name="Copied" /> An app's own template [Set through Template or a Style, different layout, same names] <ControlTemplate TargetType="local:CopyField"> <Button x:Name="CopyButton" /> <VisualState x:Name="Normal" /> <VisualState x:Name="Copied" /> replaces DefaultStyleKey selects the default style finds parts and states by name in the applied template an app's template takes the default's place

Where Each Binding Finds Its Source

Structure

x:Bind starts at the page class, {Binding} at the inherited DataContext.

Where x:Bind and Binding resolve their paths in a WinUI page A page's element tree runs from the Page, whose DataContext is set to the view model, through a StackPanel to three children: a TextBlock with Text bound by x:Bind to ViewModel.Title, a TextBlock with Text bound by Binding to Title, and a ListView whose ItemsSource is bound by x:Bind to ViewModel.Orders. The ListView's DataTemplate, with x:DataType Order, holds a TextBlock bound by x:Bind to Number. The Page's DataContext is the OrderViewModel, and the StackPanel and its children inherit it. The x:Bind binding on the page resolves against the page class, OrdersPage, whose ViewModel property holds the same OrderViewModel. The Binding resolves against the DataContext it inherits down the tree, which is the OrderViewModel with its Title and Orders properties. Inside the DataTemplate, the binding resolves against the Order item the template is showing, one of the items in Orders. PAGE CLASS OrdersPage.xaml.cs [Root of every x:Bind path on the page] ViewModel property, holding the OrderViewModel; named elements ELEMENT TREE Page DataContext = ViewModel StackPanel inherits DataContext TextBlock Text="{x:Bind ViewModel.Title}" TextBlock Text="{Binding Title}" ListView ItemsSource="{x:Bind ViewModel.Orders}" [DataTemplate x:DataType="local:Order"] TextBlock Text="{x:Bind Number}" DATA OBJECTS OrderViewModel [The page's DataContext] Title Orders Order [One item in Orders] ViewModel property DataContext x:Bind: the page class, or the item inside a template {Binding}: the DataContext inherited down the tree the object a property holds

One Search Through View, View Model, and Model

C4 · Dynamic

How typing, enabling, clicking, and results move between the three layers.

The property, CanExecute, and command loop between a WinUI view, its view model, and the model Three columns: the view with a TextBox, a Search Button, and a ListView; the view model with the SearchQuery property, SearchCommand with its CanSearch check, and the Results property; and the model with IProductService. Step 1: the TextBox's two-way binding writes the typed text to SearchQuery. Step 2: the generated SearchQuery setter calls NotifyCanExecuteChanged on SearchCommand. Step 3: SearchCommand raises CanExecuteChanged, and the Button calls CanExecute, which runs CanSearch, and enables or disables itself. Step 4: a click calls Execute on SearchCommand, which runs SearchAsync. Step 5: SearchAsync awaits IProductService. Step 6: it assigns the returned products to Results. Step 7: Results raises PropertyChanged and the ListView bound to it updates. VIEW VIEW MODEL MODEL TextBox [Text bound TwoWay] Button "Search" [Command bound] ListView [ItemsSource bound OneWay] SearchQuery [Observable property] SearchCommand [CanExecute = CanSearch] Results [Observable property] IProductService [SearchAsync] 1 2 3 4 5 6 7 1 The two-way binding writes the typed text to SearchQuery. 2 The generated setter calls NotifyCanExecuteChanged on SearchCommand. 3 CanExecuteChanged fires; the button calls CanExecute and enables or disables. 4 A click calls Execute, which runs SearchAsync. 5 SearchAsync awaits the service. 6 The returned products are assigned to Results. 7 Results raises PropertyChanged; the ListView updates.

One UI Thread and Its Queue

Flow

Work from other threads reaches XAML objects only through the queue.

How work from other threads reaches a WinUI UI thread through its DispatcherQueue Left: two sources of work off the UI thread. An await or Progress of T posts its continuation through the DispatcherQueueSynchronizationContext, and background work such as Task.Run, a timer callback, or a service event calls TryEnqueue. Both add items to the UI thread's DispatcherQueue in the middle, which holds High, Normal, and Low priority lanes. The UI thread's message loop on the right takes the next item, highest priority first, and runs it, and only that code reads and writes the XAML objects: the window, its controls, and bound view model state. A dashed line from the background work straight to the XAML objects shows direct access from another thread, which throws RPC_E_WRONG_THREAD. OTHER THREADS UI THREAD'S QUEUE UI THREAD await or Progress<T> [DispatcherQueueSynchronizationContext] Background work [Task.Run, timer callback, service event] DispatcherQueue [one per UI thread, runs items serially] High Normal Low Message loop [takes the next item, highest priority first, and runs it to completion] XAML objects [Window, controls, and bound view model state, all owned by the UI thread] Post TryEnqueue next item reads and writes direct access from another thread throws RPC_E_WRONG_THREAD Work handed to the UI thread through its queue A XAML object touched from a thread that doesn't own it

One Service Scope per Window

Structure

Shared singletons in the root, and each window's services in its own scope.

A root service provider shared by two windows, each with its own service scope At the top, the root provider, App.Current.Services, holds singletons such as IProductService, shared by every window. Below it are two document windows. Each window holds its own scope, created when the window opens, containing its NavigationService, DocumentSession, and view models. Each scope's services receive the shared singletons from the root. In each window, a page shown in the window's ContentFrame finds its window's scope by calling WindowScopes.For with its Frame. Closing a window disposes its scope and everything the scope created, while the root and its singletons remain. Root provider [App.Current.Services] Singletons such as IProductService DOCUMENTWINDOW A Window scope [IServiceScope, created when the window opens] NavigationService, DocumentSession, view models ContentFrame > ProductsPage [resolves its view model in OnNavigatedTo] DOCUMENTWINDOW B Window scope [IServiceScope, created when the window opens] NavigationService, DocumentSession, view models ContentFrame > ProductsPage [resolves its view model in OnNavigatedTo] scoped services receive shared singletons WindowScopes.For(Frame) WindowScopes.For(Frame) Closing a window disposes its scope and everything the scope created. The root and its singletons stay alive.

How a Resource Reference Is Resolved

Flow

The search from the referencing element up to system resources, stopping at the first match.

The order in which WinUI searches for a XAML resource key On the left, a column of five boxes shows the search order for a StaticResource reference made by a Button. The search starts at the Button's own resources, then moves up to each parent such as a Border, then the page at the root of the XAML, then Application.Resources, and finally the system resources such as the SystemColor colors and SystemAccentColor. Arrows run downward between the boxes, and the search stops at the first box that has the key. Below the last box, a note says that a key found nowhere throws a XAML parse exception. On the right, Application.Resources is expanded to show the order inside one dictionary: first its own keys, then its merged dictionaries in reverse of the order they are declared, so Styles/Controls.xaml, then Styles/Typography.xaml, then Styles/Colors.xaml, and last XamlControlsResources, which is declared first. SEARCH ORDER FOR ONE REFERENCE INSIDE ONE DICTIONARY Button the element that makes the reference Border.Resources each parent in turn, walking up the tree Page.Resources the root of this XAML file Application.Resources including everything App.xaml merges System resources SystemColor... colors, SystemAccentColor Key found nowhere: XAML parse exception Application.Resources, searched top to bottom 1 Its own keys BrandBrush 2 Styles/Controls.xaml merged, declared last 3 Styles/Typography.xaml merged 4 Styles/Colors.xaml merged 5 XamlControlsResources merged, declared first: WinUI styles, brushes next place searched when the key isn't found one step expanded The search stops at the first match.

Fluent Easing Curves

Chart

Progress over time for the Fluent entrance and exit curves.

The Fluent entrance and exit easing curves Two charts of animation progress, from start to end, against time. The left chart shows the entrance curve, fast out, slow in, cubic-bezier(0, 0, 0, 1): progress shoots up almost immediately and then flattens, so an entering element covers most of its distance early and eases into place. The right chart shows the exit curve, slow out, fast in, cubic-bezier(1, 0, 1, 1): progress stays near the start for most of the duration and then rises steeply, so a leaving element starts slowly and accelerates away. Each chart has a dashed diagonal line for comparison, showing constant-speed linear motion. ENTERING Fast out, slow in cubic-bezier(0, 0, 0, 1) end start time arrives fast, eases into place EXITING Slow out, fast in cubic-bezier(1, 0, 1, 1) end start time starts slowly, accelerates away Fluent curve linear, for comparison

Regions of a Custom Title Bar

Structure

Which parts of an extended title bar drag the window and which take clicks.

The regions of a custom title bar in a WinUI window A horizontal strip across the top of a window, 48 pixels tall, divided from left to right. At the far left is a padding column the width of LeftInset. Next come the app icon and title, then an empty stretch, then a search box, then another empty stretch, and at the far right a padding column the width of RightInset under the system caption buttons: minimize, maximize, and close. The icon, title, and both empty stretches are caption regions, where pressing and dragging moves the window. The search box is a passthrough region, registered with InputNonClientPointerSource, so clicks reach the control. The caption buttons are drawn by the system, not by the app's XAML. Below the strip, a note says passthrough rectangles are in physical pixels measured from the window's client-area origin at the top left, and are recomputed when the title bar element changes size. TOP OF THE WINDOW, CONTENT EXTENDED INTO THE TITLE BAR page content ▣ Order Desk Search orders – □ ✕ LeftInset Caption drags the window Passthrough clicks reach the control Caption Caption buttons drawn by the system, RightInset wide caption region, the drag area passthrough rectangle, in physical pixels from the client-area origin Recompute the passthrough rectangles when the title bar element changes size.

How One Key Press Is Processed

Flow

The steps a key press passes through, from PreviewKeyDown up the tree.

The order in which WinUI processes a key press A column of rows shows the steps a key press passes through, top to bottom. First, PreviewKeyDown is raised, starting at the focused element. Next comes the focused element, a TextBox, where three steps run left to right: its keyboard accelerators, its OnKeyDown override, then its KeyDown event. The key then bubbles to the parent, a Grid, which runs the same three steps, and then to the root, a Page, which runs them again. A branch to the right of the root row shows that if the key is still unhandled, WinUI looks for unscoped accelerators elsewhere in the window, meaning accelerators with no ScopeOwner. Below the root, CharacterReceived delivers the typed character for text input. A panel on the right says that setting Handled to true at any step stops everything below it, and that an accelerator that fires marks KeyDown handled. ONE KEY PRESS, TOP TO BOTTOM PreviewKeyDown raised first, starting at the focused element TextBox has focus Accelerators OnKeyDown KeyDown bubbles to the parent Grid its parent Accelerators OnKeyDown KeyDown bubbles to the root Page the root Accelerators OnKeyDown KeyDown Unscoped accelerators elsewhere in the window, any with no ScopeOwner CharacterReceived the typed character, for text input Handled = true at any step stops everything below it. An accelerator that fires marks KeyDown handled, so no KeyDown runs after it. next step, reached only while the key is still unhandled

Redirecting a Second Launch to the Running Instance

C4 · Dynamic

A second launch finds the running instance by key, hands over its activation, and exits.

How a single-instance WinUI app redirects a second launch Two columns show two processes of the same app. On the right, the running instance called FindOrRegisterForKey with the key main at its own startup, got IsCurrent true, and kept the key. On the left, a second launch starts a new process. Its custom Main reads its activation with GetActivatedEventArgs, then calls FindOrRegisterForKey with the same key. A dashed line shows that this call finds the running instance by key, so it returns that instance with IsCurrent false. The new process then calls RedirectActivationToAsync with its activation arguments and brings the running instance's window forward, and an arrow carries the activation across to the running instance, where the Activated event receives the same AppActivationArguments. The running instance then activates its window and routes the activation on the UI thread. The second process returns from Main and exits without creating a window. SECOND LAUNCH: NEW PROCESS RUNNING INSTANCE GetActivatedEventArgs() in the custom Main: why this launch happened FindOrRegisterForKey("main") returns the running instance, IsCurrent = false RedirectActivationToAsync(args) hands the activation over, then brings that window forward Return from Main the process exits without creating a window FindOrRegisterForKey("main") at its own startup: IsCurrent = true, keeps the key later Activated event receives the same AppActivationArguments Activate window, route on the UI thread, through the navigation service finds by key activation next step in the same process activation handed across processes lookup by key

Focus Crossing a XAML Island

Flow

Where an island sits inside a host window, and how Tab crosses its edge.

How keyboard focus crosses the boundary of a WinUI XAML island A large box is the host window, built with WPF, WinForms, or Win32. On its left are two host controls, a name text box above and a Save button below. On its right, a dashed box is the island: a DesktopWindowXamlSource whose DesktopChildSiteBridge child window sits inside the host window, positioned by MoveAndResize. Inside the island is the WinUI content, a SettingsPanel with a first WinUI control at the top and a last WinUI control at the bottom. An arrow runs from the name text box to the first WinUI control, labeled Tab into the island, where the host calls NavigateFocus with First. A second arrow runs from the last WinUI control back to the Save button, labeled Tab past the island's last control, where the island raises TakeFocusRequested and the host moves focus on. A note says Shift+Tab reverses both paths, with NavigateFocus using Last. HOST WINDOW: WPF, WINFORMS, OR WIN32 Name text box host control Save button host control DesktopWindowXamlSource the island: a DesktopChildSiteBridge child window, placed with SiteBridge.MoveAndResize WinUI content (SettingsPanel) First WinUI control Last WinUI control … other controls Tab in host calls NavigateFocus(First) Tab out island raises TakeFocusRequested, host focuses its next control keyboard focus crossing the island's edge. Shift+Tab reverses both paths, with NavigateFocus(Last)

Where the Windows App SDK Runtime Lives

C4 · Deployment

Apps sharing one serviced runtime, beside an app that carries its own copy.

Framework-dependent and self-contained deployment of the Windows App SDK runtime The left panel shows framework-dependent deployment. Three apps sit at the top: packaged app A, packaged app B (each declaring the framework as a manifest dependency), and unpackaged app C, which finds the runtime through its bootstrapper. Arrows run from all three down to one shared Framework package, the Windows App SDK runtime installed once and shared by every app that uses it. Below the framework, the Main package updates it from the Store, shown by an arrow into the framework labeled servicing updates, and the DDLM (Dynamic Dependency Lifetime Manager) holds the framework version that unpackaged app C (or an app packaged with external location) is using, so it isn't updated while C runs. The right panel shows self-contained deployment: app D contains its own copy of the runtime inside the app, which changes only when the app ships a new version. FRAMEWORK-DEPENDENT Packaged app A manifest dependency Packaged app B manifest dependency Unpackaged app C uses the bootstrapper Framework package the runtime, one shared copy for every app using it Main package updates it from the Store DDLM holds app C's version while C runs servicing updates SELF-CONTAINED App D its own files, packaged or not Runtime copy inside the app, not shared Changes only when App D ships a new version app loads the runtime servicing update keeps a version in use

Migrating a WPF App Screen by Screen

Structure

A WPF window hosting a ported WinUI screen, with both UIs bound to one shared view model library.

A WPF shell hosting a WinUI 3 island during a gradual migration A WPF main window is the outer shell. Inside it, on the left, are WPF screens not yet ported, drawn in WPF controls. On the right is a DesktopWindowXamlSource, the XAML Island, hosting a WinUI 3 screen that has already been ported. Below the window sits a shared class library targeting plain .NET, holding view models and services. Arrows run from both the WPF screens and the WinUI screen down to the same view models, showing that both UIs bind to one set of view models, so the two screens stay in sync without referencing each other. A dashed arrow from a WPF screen to the island marks a screen being ported, which moves from the WPF side to the island side. WPF MAIN WINDOW (THE SHELL) Orders screen WPF controls, not yet ported Settings screen WPF controls, not yet ported DesktopWindowXamlSource the XAML Island, a region of the WPF window Customers screen WinUI 3 controls, already ported Shared class library (plain .NET) view models and service interfaces, no WPF or WinUI references WPF binding WinUI binding a screen being ported

A Composition Effect on a XAML Element

Structure

How a hand-in visual attaches to an element and gets its pixels.

How a frosted-glass composition effect attaches to a XAML element Three columns. The left column is the XAML tree: a Grid with two children, an Image and an empty Canvas named GlassHost. The middle column is the composition visuals: each XAML element is backed by a handout Visual that GetElementVisual returns, and XAML sets its Offset, Size, and Opacity. The composition visuals form the same tree as the XAML elements. Under the GlassHost visual, the app attaches a hand-in SpriteVisual with SetElementChildVisual, as the last child, so it draws on top of the element. The right column is the brush graph that paints the sprite. A CompositionBackdropBrush supplies the pixels behind the sprite. It plugs into the source parameter of a GaussianBlurEffect, a Win2D effect description. CreateEffectFactory compiles that description and CreateBrush makes a CompositionEffectBrush from it, which is the sprite's Brush. An expression animation keeps the sprite's Size equal to the host visual's Size. XAML TREE COMPOSITION VISUALS BRUSH GRAPH Grid layout root Image the content to blur Canvas "GlassHost" empty placeholder Visual (Grid) handout visual Visual (Image) handout visual Visual (GlassHost) XAML sets Offset, Size, Opacity SpriteVisual hand-in visual, drawn on top SetElementChildVisual attached as the last child CompositionBackdropBrush the pixels behind the sprite GaussianBlurEffect [Win2D effect description] CompositionEffectBrush set as the sprite's Brush source parameter CreateEffectFactory, then CreateBrush backed by: GetElementVisual returns the visual XAML made objects the app creates and connects An expression animation keeps the SpriteVisual's Size equal to the GlassHost visual's Size.

WebView2 Processes and User Data Folders

C4 · Deployment

Which browser process each WebView2 control uses, grouped by user data folder.

How WebView2 controls map to browser processes and user data folders On the left is the app's own process, holding three WebView2 controls. Controls 1 and 2 were created with an environment that names user data folder A. Control 3 was created with an environment that names user data folder B. In the middle are two WebView2 process groups outside the app. The group for folder A has one browser process, which both control 1 and control 2 talk to, and which starts renderer processes for the sites being shown plus GPU and utility helper processes. The group for folder B has its own browser process, which only control 3 talks to. On the right, each browser process reads and writes its own user data folder, which holds cookies, local storage, the cache, and permissions. A note says another app run by the same user that names folder A joins group A rather than starting a new browser process. APP PROCESS WebView2 control 1 environment: folder A WebView2 control 2 environment: folder A WebView2 control 3 environment: folder B PROCESS GROUP A Browser process one per folder, started by the first control Renderer site 1 Renderer site 2 plus GPU, audio, and utility helper processes PROCESS GROUP B Browser process its own renderers and helpers User data folder A cookies, storage, cache User data folder B a separate profile Another app, same user, naming folder A with the same options, joins group A. calls from the control, events and web messages both ways starts or reads and writes

OAuth2Manager Sign-In Through a Redirect

C4 · Dynamic

How the browser's redirect gets back to the app instance that started sign-in.

The OAuth2Manager authorization code flow with a protocol redirect Four participants from left to right: the app instance that starts sign-in, the user's default browser, the identity provider, and a second app instance that Windows starts for the redirect. Step 1: the first instance calls RequestAuthWithParamsAsync, which opens the provider's authorize page in the browser. Step 2: the user signs in with the provider in the browser. Step 3: the provider redirects the browser to the app's own protocol, contoso-app, with an authorization code. Step 4: Windows handles that protocol by activating the app, which starts a second instance. Step 5: the second instance calls CompleteAuthRequest with the redirect URI, which hands it to the first instance, and the second instance exits. Step 6: the first instance, whose request has now returned, calls RequestTokenAsync with the code and the PKCE verifier and receives tokens from the provider. App instance 1 starts sign-in Default browser not embedded in the app Identity provider authorize and token App instance 2 started for the redirect 1 RequestAuthWithParamsAsync 2 user signs in 3 redirect to contoso-app:/oauth-callback/?code= 4 Windows activates the app 5 CompleteAuthRequest, then exit 6 RequestTokenAsync: code and PKCE verifier, tokens back Step 5 completes the request instance 1 started in step 1, so its await returns and step 6 runs there.

Elements, Automation Peers, and What Narrator Reads

Structure

Each element's peer decides what a screen reader announces.

How four XAML elements become entries in the UI Automation control view through their automation peers Four elements on a page are shown in the left column, each connected to its automation peer in the middle column, and each peer connected to what Narrator announces in the right column. A Button with AutomationProperties.Name set to Settings gets a built-in ButtonAutomationPeer with the Invoke pattern, and Narrator announces "Settings, button". A divider Rectangle with AccessibilityView set to Raw is kept out of the control view, so nothing is announced. A TextBlock reading Orders with HeadingLevel set to Level1 gets a built-in TextBlockAutomationPeer, and Narrator announces "Orders, heading level 1". A custom StarRating control named Rating overrides OnCreateAutomationPeer to return a custom StarRatingAutomationPeer with the RangeValue pattern, and Narrator announces "Rating, slider, 3". A dashed arrow runs back from the rating's announcement to the StarRating control, showing that a pattern call such as SetValue from the screen reader goes through the peer into the control's own logic. ELEMENTS ON THE PAGE AUTOMATION PEERS WHAT NARRATOR READS Button AutomationProperties.Name="Settings" ButtonAutomationPeer [Built in] Invoke pattern "Settings, button" Rectangle (divider) AccessibilityView="Raw" Out of the control view [Raw view only, for diagnostic tools] (nothing announced) TextBlock "Orders" HeadingLevel="Level1" TextBlockAutomationPeer [Built in] reports the heading level "Orders, heading level 1" StarRating (custom Control) overrides OnCreateAutomationPeer StarRatingAutomationPeer [Custom] Slider role, RangeValue pattern "Rating, slider, 3" SetValue from the screen reader runs through the peer into the control's own logic the element creates its peer, and the peer reports name, role, and value a pattern call coming back from the screen reader

Found this useful? Share it:

Share on LinkedIn