背水一戰 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null
作者:webabcd
介紹
背水一戰 Windows 10 之 XAML
- x:DeferLoadStrategy="Lazy" - 用於指定一個 UIElement 為一個延遲加載元素
- x:Null - null
示例
1、x:DeferLoadStrategy 通過 FindName 加載
Xaml/DeferLoadStrategy/Demo1.xaml
<Page x:Class="Windows10.Xaml.DeferLoadStrategy.Demo1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml.DeferLoadStrategy" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBlock Name="lblMsg" TextWrapping="Wrap" Margin="5" /> <!-- x:DeferLoadStrategy="Lazy" - 其僅作用於 UIElement,可以指定一個 UIElement 為一個延遲加載元素 1、標記為延遲加載的元素必須要指定其 x:Name 2、UIElement 不是在任何情況下都能標記為 x:DeferLoadStrategy="Lazy" 的,不是只有 FindName 才能加載延遲加載元素,具體參見文檔:https://msdn.microsoft.com/en-us/windows/uwp/xaml-platform/x-deferloadstrategy-attribute 3、將 UIElement 標記為 x:DeferLoadStrategy="Lazy" 的好處是可以減少頁面的啟動時間,帶來的問題是會增加內存的使用量,每個延遲加載元素大約多耗費 600 字節左右的內存 4、延遲加載元素在加載后,會觸發其 Loading 事件 --> <TextBlock Name="textBlock" Margin="5" x:DeferLoadStrategy="Lazy" /> </StackPanel> </Grid> </Page>
Xaml/DeferLoadStrategy/Demo1.xaml.cs
/* * 演示 x:DeferLoadStrategy 的相關知識點 * * 本例演示通過“FindName”加載延遲加載元素 */ using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10.Xaml.DeferLoadStrategy { public sealed partial class Demo1 : Page { public Demo1() { this.InitializeComponent(); this.Loaded += DeferLoadStrategyDemo_Loaded; } private void DeferLoadStrategyDemo_Loaded(object sender, RoutedEventArgs e) { try { // 拋出異常 textBlock.Text = "我是 TextBlock"; } catch (Exception ex) { lblMsg.Text += ex.ToString(); lblMsg.Text += Environment.NewLine; } // 可以通過 FindName() 來加載 x:DeferLoadStrategy="Lazy" 元素 this.FindName(nameof(textBlock)); textBlock.Text = "我是 TextBlock"; } } }
2、x:DeferLoadStrategy 通過綁定加載
Xaml/DeferLoadStrategy/Demo2.xaml
<Page x:Class="Windows10.Xaml.DeferLoadStrategy.Demo2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml.DeferLoadStrategy" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBox Name="textBox1" Margin="5" /> <!--延遲加載元素--> <TextBox Name="textBox2" x:DeferLoadStrategy="Lazy" Text="我是 TextBox" Margin="5" /> <!--將 textBox2 與 textBox1 綁定后,textBox2 就會被加載--> <Button Name="button" Content="將 textBox1 的 Text 綁定到 textBox2 的 Text" Click="button_Click" Margin="5" /> </StackPanel> </Grid> </Page>
Xaml/DeferLoadStrategy/Demo2.xaml.cs
/* * 演示 x:DeferLoadStrategy 的相關知識點 * * 本例演示通過“綁定”加載延遲加載元素 */ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Data; namespace Windows10.Xaml.DeferLoadStrategy { public sealed partial class Demo2 : Page { public Demo2() { this.InitializeComponent(); } private void button_Click(object sender, RoutedEventArgs e) { // 實例化 Binding 對象 Binding binding = new Binding() { ElementName = nameof(textBox2), // textBox2 是延遲加載元素,將其與 textBox1 綁定后,textBox2 就會被加載 Path = new PropertyPath(nameof(TextBox.Text)), Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged }; // 將目標對象的目標屬性與指定的 Binding 對象關聯 BindingOperations.SetBinding(textBox1, TextBox.TextProperty, binding); } } }
3、x:DeferLoadStrategy 通過 Storyboard 加載
Xaml/DeferLoadStrategy/Demo3.xaml
<Page x:Class="Windows10.Xaml.DeferLoadStrategy.Demo3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml.DeferLoadStrategy" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Storyboard x:Name="sb"> <ColorAnimation Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(Ellipse.Fill).(SolidColorBrush.Color)" BeginTime="00:00:00" From="Orange" To="Blue" Duration="0:0:3" AutoReverse="true" RepeatBehavior="Forever "> </ColorAnimation> </Storyboard> </Page.Resources> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <!--延遲加載元素--> <Ellipse x:Name="ellipse" Fill="Orange" Width="200" Height="100" x:DeferLoadStrategy="Lazy" HorizontalAlignment="Left" Margin="5" /> <!--啟動一個引用了延遲加載元素的動畫后,該延遲加載元素就會被加載--> <Button Name="button" Content="開始動畫" Click="button_Click" Margin="5" /> </StackPanel> </Grid> </Page>
Xaml/DeferLoadStrategy/Demo3.xaml.cs
/* * 演示 x:DeferLoadStrategy 的相關知識點 * * 本例演示通過“Storyboard”加載延遲加載元素 */ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10.Xaml.DeferLoadStrategy { public sealed partial class Demo3 : Page { public Demo3() { this.InitializeComponent(); } private void button_Click(object sender, RoutedEventArgs e) { // 啟動一個引用了延遲加載元素的動畫后,該延遲加載元素就會被加載 sb.Begin(); } } }
4、x:DeferLoadStrategy 通過 Setter 加載
Xaml/DeferLoadStrategy/Demo4.xaml
<Page x:Class="Windows10.Xaml.DeferLoadStrategy.Demo4" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml.DeferLoadStrategy" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="WindowSizeStates"> <VisualState> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="360" /> </VisualState.StateTriggers> </VisualState> <VisualState> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0" /> </VisualState.StateTriggers> <VisualState.Setters> <!--窗口寬度小於 360 時調用,此處 setter 引用了延遲加載元素,該延遲加載元素將會被加載--> <Setter Target="textBox.Foreground" Value="Red" /> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <StackPanel Margin="10 0 10 10"> <!--延遲加載元素--> <TextBox Name="textBox" Text="我是 TextBox" x:DeferLoadStrategy="Lazy" /> </StackPanel> </Grid> </Page>
Xaml/DeferLoadStrategy/Demo4.xaml.cs
/* * 演示 x:DeferLoadStrategy 的相關知識點 * * 本例演示通過“Setter”加載延遲加載元素 */ using Windows.UI.Xaml.Controls; namespace Windows10.Xaml.DeferLoadStrategy { public sealed partial class Demo4 : Page { public Demo4() { this.InitializeComponent(); } } }
5、x:DeferLoadStrategy 通過 GetTemplateChild 加載
Xaml/DeferLoadStrategy/Demo5.xaml
<Page x:Class="Windows10.Xaml.DeferLoadStrategy.Demo5" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml.DeferLoadStrategy" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Page.Resources> <Style TargetType="local:TitledImage"> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:TitledImage"> <Grid> <Image Source="{TemplateBinding Source}" Width="200" Height="100" Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center" /> <!--延遲加載元素,當調用 GetTemplateChild 后,它將被加載--> <ContentPresenter x:Name="TitlePresenter" x:DeferLoadStrategy="Lazy" Content="{TemplateBinding Title}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="White" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Page.Resources> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <!--對應的 ControlTemplate 中的延遲加載元素 TitlePresenter 不會被加載--> <local:TitledImage Source="/Assets/SplashScreen.png" /> <!--對應的 ControlTemplate 中的延遲加載元素 TitlePresenter 會被加載(因為調用了 GetTemplateChild)--> <local:TitledImage Source="/Assets/SplashScreen.png" Title="image title" /> </StackPanel> </Grid> </Page>
Xaml/DeferLoadStrategy/Demo5.xaml.cs
/* * 演示 x:DeferLoadStrategy 的相關知識點 * * 本例演示通過“GetTemplateChild”加載延遲加載元素 */ using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media.Imaging; namespace Windows10.Xaml.DeferLoadStrategy { public sealed partial class Demo5 : Page { public Demo5() { this.InitializeComponent(); } } // 自定義控件(一個可顯示 Title 的 Image) public class TitledImage : Control { // 此自定義控件用於顯示 Title 的 ContentPresenter private ContentPresenter _titlePresenter; public TitledImage() { this.DefaultStyleKey = typeof(TitledImage); // 注冊一個回調,當 Title 發生變化時觸發 this.RegisterPropertyChangedCallback(TitleProperty, TitleChanged); } // 定義一個依賴屬性 Title(用於顯示標題) public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(TitledImage), new PropertyMetadata(null)); public string Title { get { return (string)GetValue(TitleProperty); } set { SetValue(TitleProperty, value); } } // 定義一個依賴屬性 Source(用於顯示圖片) public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(nameof(Source), typeof(ImageSource), typeof(TitledImage), new PropertyMetadata(null)); public ImageSource Source { get { return (BitmapSource)GetValue(SourceProperty); } set { SetValue(SourceProperty, value); } } void TitleChanged(DependencyObject sender, DependencyProperty prop) { string title = (string)sender.GetValue(prop); if (!string.IsNullOrEmpty(Title) && _titlePresenter == null) { // TitlePresenter 是控件模板中的一個延遲加載元素,通過 GetTemplateChild 調用后,它將被加載 _titlePresenter = (ContentPresenter)GetTemplateChild("TitlePresenter"); } } protected override void OnApplyTemplate() { base.OnApplyTemplate(); if (!string.IsNullOrEmpty(Title)) { // TitlePresenter 是控件模板中的一個延遲加載元素,通過 GetTemplateChild 調用后,它將被加載 _titlePresenter = (ContentPresenter)GetTemplateChild("TitlePresenter"); } } } }
6、x:Null - null
Xaml/NullDemo.xaml
<Page x:Class="Windows10.Xaml.NullDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:Windows10.Xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="10 0 10 10"> <TextBlock Name="lblMsg" TextWrapping="Wrap" Margin="5" /> <!--不指定 Tag 則其默認值為 null--> <TextBlock Name="textBlock1" Margin="5" /> <!--指定 Tag 的值為 ""--> <TextBlock Name="textBlock2" Margin="5" Tag="" /> <!--指定 Tag 的值為 null--> <TextBlock Name="textBlock3" Margin="5" Tag="{x:Null}" /> </StackPanel> </Grid> </Page>
Xaml/NullDemo.xaml.cs
/* * 演示 x:Null 的相關知識點、 * * 在這里插一句: * 在 xaml 使用的 {x:Null}, {Binding}, {x:Bind}, {StaticResource} 之類的這種帶大括號的語法被稱為標記擴展(Markup Extension),在 uwp 中無法開發自定義標記擴展(但是在 wpf 中是可以的) */ using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Windows10.Xaml { public sealed partial class NullDemo : Page { public NullDemo() { this.InitializeComponent(); this.Loaded += NullDemo_Loaded; } private void NullDemo_Loaded(object sender, RoutedEventArgs e) { lblMsg.Text = $"textBlock1.Tag: {textBlock1.Tag ?? "null"}"; // null lblMsg.Text += Environment.NewLine; lblMsg.Text += $"textBlock2.Tag: {textBlock2.Tag ?? "null"}"; // "" lblMsg.Text += Environment.NewLine; lblMsg.Text += $"textBlock3.Tag: {textBlock3.Tag ?? "null"}"; // null } } }
OK
[源碼下載]