背水一戰 Windows 10 (26) - XAML: x:DeferLoadStrategy, x:Null


[源碼下載]


背水一戰 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
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM