[WP8.1UI控件編程]Windows Phone XAML頁面的編譯


1.1.2 XAML頁面的編譯

    Windows Phone的應用程序項目會通過Visual Studio完成XAML頁面的編譯,在程序運行時會通過直接鏈接操作加載和解析XAML,將XAML和過程式代碼自動連接起來。如果你不在乎將XAML文件和過程式代碼融合,那么只需要把它添加到Visual Studio的Windows Phone項目中來,並用界面中的Build動作來完成編譯即可,一般公共的樣式資源的XAML文件都是采用這種方式。但是如果要編譯一個XAML文件並將它與過程式代碼混合,第一步要做的就是為XAML文件的根元素指定一個子類,可以用XAML語言命名空間中的Class關鍵字來完成,一般Windows Phone的程序頁面是采用這種方式,通常在Windows Phone項目新增的XAML文件都會自動地生成一個對應的XAML.CS文件,並且默認地將兩個文件關聯起來,例如,添加的XAML文件如下:

    < Page
        x:Class="PhoneApp1.MainPage"
        ……>
        ……省略若干代碼
    </ Page>

與XAML文件關聯起來的XAML.CS文件如下:

namespace PhoneApp1
{
    public sealed partial class MainPage : Page
    {
    ……省略若干代碼
    }
}

    通常我們把與XAML文件關聯的XAML.CS文件叫作代碼隱藏文件。如果你引用XAML中的任何一個事件處理程序(通過事件特性,如Button的Click特性),這里就是我們定義這些事件處理程序的地方。類定義中的partial關鍵字很重要,因為類的實現是分布在多個文件中的。可能你會覺得奇怪,因為在項目里面只看到了MainPage.xaml.cs文件定義了MainPage類,其實MainPage類還在另外一個地方定義了,只是在項目工程里面隱藏了而已。當我們編譯完Windows Phone的項目時,你會在項目的obj\Debug文件夾下看到Visual Studio創建的以g.cs為擴展名的文件,對於每一個XAML文件,你會找到對應有一個g.cs文件。例如,如果我們項目中有一個MainPage.xaml文件,你就會在obj\Debug文件夾下找到MainPage.g.cs文件。下面來看一下MainPage.g.cs文件的結構:

using System;
……
namespace PhoneApp1 {
    public partial class MainPage : global::Windows.UI.Xaml.Controls.Page {
        [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Windows.UI.Xaml.Build.Tasks"," 4.0.0.0")]
        (global::Windows.UI.Xaml.Controls.Grid LayoutRoot;
        ……
        private bool _contentLoaded;
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        public void InitializeComponent() {
            if (_contentLoaded) {
                return;
            }
            _contentLoaded = true;
            global::Windows.UI.Xaml.Application.LoadComponent(this, new global::System.Uri("ms-appx:///MainPage.xaml"), global::Windows.UI.Xaml.Controls.Primitives.ComponentResourceLocation.Application);
            LayoutRoot = (global::Windows.UI.Xaml.Controls. Grid)this.FindName("LayoutRoot"); 
           ……
        }
    }
}

    從MainPage.g.cs文件中我們可以看到,MainPage類在這里還定義了一些控件和相關的方法,並且InitializeComponent()方法里面加載和解析了MainPage.xaml文件MainPage.cs文件里面的MainPage()方面里面調用的InitializeComponent()方法就是在MainPage.g.cs文件里面定義的。在xaml頁面中聲明的控件,通常會在.g.cs中生成對應控件的內部字段。實際上這取決於控件是否有x:Name屬性,只要有這個屬性,都會自動調用FindName方法,用於把字段和頁面控件關聯。沒有x:Name屬性,則沒有字段,這種關聯會有一定的性能浪費,因為是在應用載入控件的時候,通過LoadComponents方法關聯的,而xaml也是在這個時候動態解析的。

    在項目的obj\Debug文件夾下,我們還找到了g.i.cs為擴展名的文件,對於每一個XAML文件,你也會找到對應有一個g.i.cs文件,並且這些g.i.cs文件與對應的g.cs文件是基本一樣的。那么這些g.i.cs文件又有怎樣的含義呢?其實這些g.i.cs文件並不是在編譯的時候生成的,而是當你創建了XAML文件的時候就馬上生成,或者你修改了XAML文件g.i.cs文件也會跟着改變,而g.cs文件則是必須要成功編譯了項目之后才會生成的。文件后綴中的g表示generated產生的意思,i表示intellisense智能感知的意思,g.i.cs文件是XAML文件對應的智能感知文件,在vs中利用go to definition功能找InitializeComponent方法的實現的時候,進入的就是g.i.cs文件的InitializeComponent方法里面。

1.1.3 動態加載XAML

    動態加載XAML是指在程序運行時通過解析XAML格式的字符串或者文件來動態生成UI的效果。通常情況下,Windows Phone的界面元素都是通過直接讀取XAML文件的內容來呈現的,如上一小節講解的那樣通過XAML文件和XAML.CS文件關聯起來編譯,這也是默認的UI實現的方式,但是在某些時候你並不能預先設計好所有的XAML元素,而是需要在程序運行的過程中動態地加載XAML對象,那么這時候就需要使用到動態加載XAML來實現了。

    在應用程序里面動態加載XAML需要使用到XamlReader.Load方法來實現,XamlReader 類是為分析 XAML 和創建相應的 Windows Phone 對象樹提供 XAML 處理器引擎,XamlReader.Load 方法可以分析格式良好的 XAML 片段並創建相應的 Windows Phone對象樹,然后返回該對象樹的根。大部分可以再XAML頁面上編寫的代碼,我們都可以通過動態加載XAML的形式來實現,不僅僅是普通的UI控件,動畫等其他的XAML代碼我們一樣可以動態加載,如:

        // 一個透明度變化動畫的XAML代碼的字符串
        private const string FadeInStoryboard =
        @"<Storyboard xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"">
            <DoubleAnimation 
                Duration=""0:0:0.2"" 
                Storyboard.TargetProperty=""(UIElement.Opacity)"" 
                To=""1""/>
        </Storyboard>";
    //使用XamlReader.Load方法加載XAML字符串並且解析成動畫對象
    Storyboard storyboard = XamlReader.Load(FadeInStoryboard) as Storyboard;

使用 XamlReader.Load方法動態加載XAML對XAML的字符串是有一定的要求的,那么這些“格式良好的 XAML 片段”必須要符合以下要求:

    (1)XAML 內容字符串必須定義單個根元素,使用XamlReader.Load創建的內容只能賦予一個Windows Phone對象,它們是一對一的關系。

    (2)內容字符串 XAML 必須是格式良好的 XML,並且必須是可分析 XAML。

    (3)所需的根元素還必須指定某一默認的 XML 命名空間值。這通常是命名空間 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"。

下面給出動態加載XAML的示例: 演示了使用XamlReader.Load方法加載XAML字符串生成一個按鈕和加載XAML文件生成一個矩形。
    代碼清單1-1動態加載XAML(源代碼:第1章\Examples_1_1)

MainPage.xaml文件主要代碼
------------------------------------------------------------------------------------------------------------------
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel x:Name="sp_show">
                <Button x:Name="bt_addXAML" Content="加載XAML按鈕" Click="bt_addXAML_Click"></Button>
            </StackPanel>
        </Grid>
Rectangle.xaml文件代碼:被動態加載到程序里面去的XAML文件
------------------------------------------------------------------------------------------------------------------
<Rectangle xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Height="200" Width="480">
    <Rectangle.Fill>
        <LinearGradientBrush>
            <GradientStop Color="Black" Offset="0"/>
            <GradientStop Color="Red" Offset="0.5"/>
            <GradientStop Color="Black" Offset="1"/>
        </LinearGradientBrush  >
    </Rectangle.Fill>
</Rectangle>
MainPage.xaml.cs文件主要代碼
------------------------------------------------------------------------------------------------------------------
        // 加載XAML按鈕
        private void bt_addXAML_Click(object sender, RoutedEventArgs e)
        {
            //注意XAML字符串里面的命名空間"http://schemas.microsoft.com/winfx/2006/xaml/presentation" 不能少。
            string buttonXAML = "<Button xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'  " +
                 " Content=\"加載XAML文件\"  Foreground=\"Red\"></Button>";
            Button btnRed = (Button)XamlReader.Load(buttonXAML);
            btnRed.Click += btnRed_Click;
            sp_show.Children.Add(btnRed);
        }
        // 已加載的XAML按鈕關聯的事件
        async void btnRed_Click(object sender, RoutedEventArgs e)
        {
            string xaml = string.Empty;
            //加載程序的Rectangle.xaml文件
            StorageFile fileRead = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync("Rectangle.xaml");
            // 讀取文件的內容
    xaml = await FileIO.ReadTextAsync(fileRead);
            // 加載Rectangle
            Rectangle rectangle = (Rectangle)XamlReader.Load(xaml);
            sp_show.Children.Add(rectangle);
        }

本文來源於《深入理解Windows Phone 8.1 UI控件編程》

源代碼下載:http://vdisk.weibo.com/s/zt_pyrfNHoezI

歡迎關注我的微博@WP林政

WP8.1技術交流群:372552293


免責聲明!

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



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