Windows 10 开发 - XAML 性能
应用程序的性能非常重要,例如应用程序在启动时显示的速度、导航到显示下一个内容的速度等等。
应用程序的性能受多种因素影响,包括 XAML 渲染引擎解析应用程序中所有 XAML 代码的能力。XAML 是一个非常强大的 UI 创建工具,但使用 Windows 10 应用程序中现在提供的新技术可以使其更加健壮。
例如,在您的应用程序中,有些内容您希望在页面加载时显示,但之后不再需要。启动时,您也可能不需要加载所有 UI 元素。
Windows 10 应用在 XAML 中添加了一些新功能,从而提升了 XAML 的性能。
任何通用 Windows 应用的性能都可以通过以下技术来提升;
- 渐进式渲染
- 延迟加载
渐进式渲染
Windows 10 在 XAML 中引入了两个非常酷炫的新功能。它们是 −
x:Bind
这是 XAML 中引入的一种用于绑定的新语法,其工作方式与 Binding 语法几乎相同。x:Bind 有两个主要区别;它提供编译时语法验证和更佳性能。
X:Phase
它能够优先处理数据模板中 XAML 控件的渲染。每个 UI 元素只能指定一个阶段。如果指定,则该阶段将应用于元素上的所有绑定。如果未指定阶段,则假定为阶段 0。
在通用 Windows 平台 (UWP) 应用程序中,这两个新功能可提升性能。它也可以用于迁移到 Windows 10 的现有 Windows 8.x 应用程序。
以下示例使用 x:Bind 关键字将员工对象与 GridView 绑定。
<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>
在上述 XAML 代码中,x:Phase = "1" 定义了 Title。因此,在第一个阶段,将渲染 Name,然后渲染 Title。
以下是 Employee 类 的 C# 实现。
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.UI.Xaml.Controls;
// 空白页项目模板的文档位于
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;
}
}
}
执行上述代码后,您将看到以下窗口。
结合使用 X:Phase 和 x:Bind 来增量渲染 ListView 和 GridView 项目,并提升平移体验。
延迟加载
延迟加载是一种技术,可通过减少应用程序启动时 XAML UI 元素的数量来最大限度地缩短启动加载时间。如果您的应用程序包含 30 个 UI 元素,并且用户在启动时不需要所有这些元素,那么所有不需要的元素都可以通过延迟加载来节省一些加载时间。
x:DeferLoadStrategy = "Lazy" 会延迟元素及其子元素的创建,这会缩短启动时间,但会略微增加内存使用量。
可以通过使用元素上定义的名称调用 FindName 来实现/创建延迟元素。
创建延迟元素后,将发生几件事 −
将引发元素上的 Loaded 事件。
将评估元素上的任何绑定。
如果应用程序已注册接收包含延迟元素的属性的属性更改通知,则通知将已提升。
以下示例使用 x:DeferLoadStrategy = "Lazy" 来表示包含四个文本块的网格,该网格在应用程序启动时不会加载,直到您加载它为止。
<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>
以下程序是点击事件的实现,其中网格在应用程序主页面上加载。
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
// 空白页项目模板的文档位于
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
}
}
}
当上述代码编译并执行后,您将只看到一个按钮。文本块在启动时不会加载。
现在,当您点击显示元素按钮时,它将加载文本块,这将提高应用程序的启动性能。

