• [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的项目时,你会在项目的objDebug文件夹下看到Visual Studio创建的以g.cs为扩展名的文件,对于每一个XAML文件,你会找到对应有一个g.cs文件。例如,如果我们项目中有一个MainPage.xaml文件,你就会在objDebug文件夹下找到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也是在这个时候动态解析的。

        在项目的objDebug文件夹下,我们还找到了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

  • 相关阅读:
    CStringArray序列化处理
    【转】C++ Incorrect Memory Usage and Corrupted Memory(模拟C++程序内存使用崩溃问题)
    【转】Native Thread for Win32 C- Creating Processes(通俗易懂,非常好)
    【转】Native Thread for Win32 B-Threads Synchronization(通俗易懂,非常好)
    【转】Native Thread for Win32 A- Create Thread(通俗易懂,非常好)
    【转】关于OnPaint的工作机制
    Window发声函数Beep、MessageBeep
    Sqlite
    VC++ Splash Window封装类CSplash
    通过代码注册COM、DLL组件
  • 原文地址:https://www.cnblogs.com/linzheng/p/3766245.html
Copyright © 2020-2023  润新知