User Tools

Site Tools


notes:uwp:xaml

XAML - General Topics

Performance

Use x:Phase to perform incremental (phased) rendering of lists declaratively using XAML. Phased rendering lets you specify the rendering priority of individual elements in a list item data template. Phasing is a feature of {x:Bind} that works with controls derived from ListViewBase.

Example (from MSDN):

<DataTemplate x:Key="PhasedFileTemplate" x:DataType="model:FileItem">
    <Grid Width="200" Height="80">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="75" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Image Grid.RowSpan="4" Source="{x:Bind ImageData}" MaxWidth="70" MaxHeight="70" x:Phase="3"/>
        <TextBlock Text="{x:Bind DisplayName}" Grid.Column="1" FontSize="8"/>
        <TextBlock Text="{x:Bind prettyDate}" Grid.Column="1" Grid.Row="1" FontSize="8" x:Phase="1"/>
        <TextBlock Text="{x:Bind prettyFileSize}" Grid.Column="1" Grid.Row="2" FontSize="8" x:Phase="2"/>
        <TextBlock Text="{x:Bind prettyImageSize}" Grid.Column="1" Grid.Row="3" FontSize="8" x:Phase="2"/>
    </Grid>
</DataTemplate>

All controls without a phase specified will be implicitly considered to be part of phase 0.

The data template describes 4 phases:

  • Phase 0 presents the DisplayName text block.
  • Phase 1 shows the prettyDate text block.
  • Phase 2 shows the prettyFileSize and prettyImageSize text blocks.
  • Phase 3 shows the image.

Use x:deferLoadstrategy (deferred loading of UI elements) to specify parts of your UI to be delay-loaded. The deferred elements aren't created when the page is loaded; instead, they're created only when they are needed to be added to the page's visual tree.

Example (from MSDN):

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid x:Name="DeferredGrid" x:DeferLoadStrategy="Lazy">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
 
        <Rectangle Height="100" Width="100" Fill="#F65314" Margin="0,0,4,4" />
        <Rectangle Height="100" Width="100" Fill="#7CBB00" Grid.Column="1" Margin="4,0,0,4" />
        <Rectangle Height="100" Width="100" Fill="#00A1F1" Grid.Row="1" Margin="0,4,4,0" />
        <Rectangle Height="100" Width="100" Fill="#FFBB00" Grid.Row="1" Grid.Column="1" Margin="4,4,0,0" />
    </Grid>
    <Button x:Name="RealizeElements" Content="Realize Elements" Click="Button_Click"/>
</Grid>
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.FindName("DeferredGrid"); // this will realize the deferred grid
}

Ways to realize an element:

  • FindName()
  • GetTemplatedChild() (for ControlTemplate)
  • Storyboard and VisualStates (because of FindName)

When you have elements in your UI that are Collapsed by default, the objects are still created at startup, even though they aren't visible. You can defer loading these elements until they are shown by setting the x:DeferLoadStrategy attribute to Lazy. This can improve startup performance.

Extesibility

To use an arbitrary .NET class (with a default ctor) in XAML, include the proper namespace with using syntax.

Example: Use an instance of System.Net.Http.HttpClient and System.Int64 in XAML:

<ListBox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ListBox.Items>
        <sysnet:HttpClient xmlns:sysnet="using:System.Net.Http" />
        <sys:Int64 xmlns:sys="using:System">100</sys:Int64>
    </ListBox.Items>
</ListBox>

Keep in mind that the XAML language namespace defines keywords for a few primitive types so you don't need to include the System namespace:

  • x:Boolean
  • x:Int32
  • x:Double
  • x:String

Finding Element

Example: Search the element's children recursively and return the desired instance. The element may be any FrameworkElement such as a Page.

...
<Button x:Name="Button1">Stop</Button>
...
Button but = (Button)element.FindName("Button1");

Example: Find en element using VisualTreeHelper:

public childItem FindVisualChild<childItem>(DependencyObject obj)
    where childItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
 
        if (child != null && child is childItem)
            return (childItem)child;
        else
        {
            childItem childOfChild = FindVisualChild<childItem>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}

Loading / Parsing

The XamlReader.Load method parses a string containing XAML, creates objects, and returns an instance of the root element.

Example: Load the root Page object:

using Windows.UI.Xaml.Markup;
...
string xaml = "...";
 
// Get the root element. We know the root element is a Page.
Page page = XamlReader.Load(xaml) as Page;
 
// The entire hierachy of objects is instantiated in memory.
// We can, for example, grab the main Grid element.
Grid grid = page.Content as Grid;

Example: Parse a XAML snippet:

using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Markup; // XamlReader
using Windows.UI.Xaml.Shapes; // Path
...
// XAML must include the standard XAML namespace declaration.
string xaml = "<Path " +
    "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' " +
    "Stroke='Red' StrokeThickness='5' StrokeLineJoin='Round' " +
    "HorizontalAlignment='Center' VerticalAlignment='Center' " +
    "Data='M 0 0 L 0 100 L 50 100 L 50 0 " +
          "M 100 0 C 90 140, 160 140, 150 0 " +
          "M 200 100 A 10 8 0 1 0 200 10'/>";
 
// Parse XAML.
Path path = XamlReader.Load(xaml) as Path;
 
// Add the parsed XAML snippet to a container element - the MainGrid grid.
MainGrid.Children.Add(path);
notes/uwp/xaml.txt · Last modified: 2017/04/03 by leszek