Windows 10 Dev - XAML Performance


Advertisements

Performance of applications such as how quickly your application appears at the startup or navigates to show the next content etc. is very important.

The performance of an application can be impacted by many things, including the ability of XAML rendering engine to parse all the XAML code you have in your application. XAML is a very powerful tool for creating UI, but it can be more robust by using the new techniques, which are now available in Windows 10 applications.

For example, in your applications, there are certain things, which you want to show when the page is loaded and then do not need it later. It is also possible that at the startup you do not need all the UI elements to be loaded.

In Windows 10 apps, some new features are added in XAML, which improved the XAML performance.

The performance of any Universal Windows application can be improved by the following techniques;

  • Progressive Rendering
  • Deferred Loading

Progressive Rendering

In Windows 10, two new and very cool features are introduced in XAML. They are −

x:Bind

It is a new syntax introduced in XAML used for binding, which works almost the same way as the Binding syntax does. x:Bind has two key differences; it provides compile-time syntax validation and better performance.

X:Phase

It provides the ability to prioritize the rendering of XAML controls within a data template. Each UI element may have only one phase specified. If so, that will apply to all the bindings on the element. If a phase is not specified, phase 0 is assumed.

In Universal Windows Platform (UWP) applications, these two new features provide performance improvements. It can be also used in existing Windows 8.x applications that migrate to Windows 10.

Given below is an example in which the employee objects are bound with GridView by using x:Bind key word.

<Page 
   x:Class = "XAMLPhase.MainPage" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "using:XAMLPhase" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   mc:Ignorable = "d">  
   
   <Grid Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
      <GridView Name = "Presidents" ItemsSource = "{Binding}" Height = "300" 
         Width = "400" Margin = "50"> 
			
         <GridView.ItemTemplate> 
            <DataTemplate x:DataType = "local:Employee"> 
				
               <StackPanel Orientation = "Horizontal" Margin = "2"> 
                  <TextBlock Text = "{x:Bind Name}" Width = "95" Margin = "2" /> 
                  <TextBlock Text = "{x:Bind Title}" Width = "95" Margin = "2"  
                     x:Phase = "1"/> 
               </StackPanel> 
					
            </DataTemplate> 
         </GridView.ItemTemplate>
			
      </GridView> 
		
   </Grid> 
	
</Page>

In the above XAML code, x:Phase = "1" is defined with Title. Therefore, in the first phase, Name will be rendered and then Title will be rendered.

Given below is the Employee class implementation in C#.

using System.Collections.ObjectModel; 
using System.ComponentModel; 
using System.Runtime.CompilerServices; 
using Windows.UI.Xaml.Controls;
  
// The Blank Page item template is documented at
   http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 
	
namespace XAMLPhase {

   /// <summary> 
      /// An empty page that can be used on its own or navigated to within a Frame. 
   /// </summary> 
	
   public sealed partial class MainPage : Page {
      public MainPage() {
         this.InitializeComponent(); 
         DataContext = Employee.GetEmployees(); 
      } 
   } 
	
   public class Employee : INotifyPropertyChanged {
      private string name; 
		
      public string Name {
         get { return name; } 
			
         set {
            name = value; 
            RaiseProperChanged(); 
         } 
      } 
		
      private string title; 
		
      public string Title {
         get { return title; }
			
         set {
            title = value; 
            RaiseProperChanged(); 
         } 
      }
		
      public static Employee GetEmployee() {
       
         var emp = new Employee() {
            Name = "Waqas", 
            Title = "Software Engineer" 
         };  
			
         return emp; 
      } 
		
      public event PropertyChangedEventHandler PropertyChanged;
		
      private void RaiseProperChanged( 
         [CallerMemberName] string caller = "") {
			
         if (PropertyChanged != null) {
            PropertyChanged(this, new PropertyChangedEventArgs(caller)); 
         } 
			
      } 
		
      public static ObservableCollection<Employee> GetEmployees() {
         var employees = new ObservableCollection<Employee>(); 
			
         employees.Add(new Employee() { Name = "Ali", Title = "Developer" }); 
         employees.Add(new Employee() { Name = "Ahmed", Title = "Programmer" }); 
         employees.Add(new Employee() { Name = "Amjad", Title = "Desiner" }); 
         employees.Add(new Employee() { Name = "Waqas", Title = "Programmer" }); 
         employees.Add(new Employee() { Name = "Bilal", Title = "Engineer" }); 
         employees.Add(new Employee() { Name = "Waqar", Title = "Manager" }); 
			
         return employees; 
      } 
		
   }
	
}

When the above given code is executed, you will see the following window.

XAML Phase

The X:Phase with x:Bind is used to render the ListView and GridView items incrementally and improve the panning experience.

Deferred Loading

Deferred loading is a technique, which can be used to minimize the startup loading time by reducing the number of XAML UI elements at the startup of an application. If your application contains 30 UI elements and the user does not need all these elements at the startup, all those elements, which are not required can save some loading time by deferring.

x:DeferLoadStrategy = "Lazy" delays the creation of an element and its children, which decreases startup time but it slightly increases memory usage.

The deferred element can be realized/created by Calling FindName with the name that was defined on the element.

Once a deferred element is created, several things will happen −

  • The Loaded event on the element will be raised.

  • Any bindings on the element will be evaluated.

  • If the application is registered to receive property change notifications on the property containing the deferred element(s), the notification will be raised.

Given below is an example in which x:DeferLoadStrategy = "Lazy" is used for grid which contains four text blocks and will not be loaded at the startup of your application, until you load it.

<Page 
   x:Class = "UWPDeferredLoading.MainPage" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "using:UWPDeferredLoading" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   mc:Ignorable = "d"> 
	
   <Grid Background = "{ThemeResource ApplicationPageBackgroundThemeBrush}"> 
      <Grid x:Name = "DeferredGrid" x:DeferLoadStrategy = "Lazy" Margin = "50"> 
         <Grid.RowDefinitions> 
            <RowDefinition Height = "Auto" /> 
            <RowDefinition Height = "Auto" /> 
         </Grid.RowDefinitions> 
			
         <Grid.ColumnDefinitions> 
            <ColumnDefinition Width = "Auto" /> 
            <ColumnDefinition Width = "Auto" /> 
         </Grid.ColumnDefinitions>
			
         <TextBlock Height = "100" Width = "100" Text = "TextBlock 1" Margin = "0,0,4,4" /> 
			
         <TextBlock Height = "100" Width = "100" Text = "TextBlock 2" 
            Grid.Column = "1" Margin = "4,0,0,4" /> 
				
         <TextBlock Height = "100" Width = "100" Text = "TextBlock 3" 
            Grid.Row = "1" Margin = "0,4,4,0" /> 
				
         <TextBlock Height = "100" Width = "100" Text = "TextBlock 4" 
            Grid.Row = "1" Grid.Column = "1" Margin = "4,4,0,0" /> 
      </Grid> 
		
      <Button x:Name = "RealizeElements" Content = "Show Elements"  
         Click = "RealizeElements_Click" Margin = "50"/> 
			
   </Grid>   
	
</Page> 

The following program is the click event implementation, in which grid is loaded on application main page.

using Windows.UI.Xaml; 
using Windows.UI.Xaml.Controls; 
 
// The Blank Page item template is documented at
   http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409  
	
namespace UWPDeferredLoading {

   /// <summary> 
      /// An empty page that can be used on its own or navigated to within a Frame. 
   /// </summary> 
	
   public sealed partial class MainPage : Page {
      public MainPage() {
         this.InitializeComponent(); 
      }  
		
      private void RealizeElements_Click(object sender, RoutedEventArgs e) {
         this.FindName("DeferredGrid"); // This will realize the deferred grid 
      } 
		
   } 
	
}

When the above code in complied and executed, you will only see a button. The Textblocks are not loaded at the startup.

UWP Different Loading

Now when you click the Show Elements button, it will load the text blocks, which will improve the startup performance of your application.

UWP Different Loading Exe
Advertisements