1. 程式人生 > >WPF -- 關於XAML語言解析處理及XAML引用

WPF -- 關於XAML語言解析處理及XAML引用

首先我們在Visual Studio中建立一個WPF專案,以下是新建的WPF程式的 xaml 檔案

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    //繪製UI相關程式集  表示(Presentation)層
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"                  
    //語言解析處理程式集語言層
    Title="MainWindow"
Height="350" Width="525">
<Grid> </Grid> </Window>

XAML引用:

XAML 中引用外來程式集和其中.NET 名稱空間

xmlns:c="clr-namespace:System.Windows.Controls; assembly=PresentationFramework"

-------------------------------------------------------------------------
c 是對映字首, 可以換成其他字串 如:"control"

因Button來自字首 c 對應的名稱空間,所以使用Button寫為  <c:Button> </c:Button>

預設引用進來的兩個名稱空間格外重要,它們對應的程式集和 .NET 名稱空間如下

    --------------------------------------------------------------
    http://schemas.microsoft.com/winfx/2006/xaml/presentation 對應:

    *System.Windows
    *System.Windows.Automarion
    *System.Windows.Controls
    *System.Windows.Controls.Primitives
    *System.Data
    *System.Windows.Documents
    *System.Windows.Forms.Integration
    *System.Windows.Ink
    *System.Windows.Input
    *System.Windows.Media
    *Syatem.Windows.Media.Animation
    *System.Windows.Media.Effects
    *System.Windows.Media.Imaging
    *System.Windows.Media.Media3D
    *System.Windows.Media.TextFormatting
    *System.Windows.Navigation
    *System.Windows.Shapes
    ---------------------------------------------------------------

XAML語言解析處理:
(一)
1.首先將x:Class=”WpfApplication1.MainWindow”這條(Attribute)語句刪掉

        <Windowx:Class="WpfApplication1.MainWindow" 刪掉這句)
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                Title
="MainWindow" Height="350" Width="525">
<Grid> </Grid> </Window>

2.再刪掉MainWindow.xaml.cs的 InitializeComponent 方法

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Data;
        using System.Windows.Documents;
        using System.Windows.Input;
        using System.Windows.Media;
        using System.Windows.Media.Imaging;
        using System.Windows.Navigation;
        using System.Windows.Shapes;

        namespace WpfApplication1
        {
            /// <summary>
            /// MainWindow.xaml 的互動邏輯
            /// </summary>
            public partial class MainWindow : Window
            {
                public MainWindow()
                {
                    //InitializeComponent();去掉這句
                }
            }
        }
    程式仍然可以執行(說明只要MainWindow.xaml 檔案能夠正確解析成一個窗體, 程式就可以正常執行)
(二)

    然後恢復 x:Class這個 Attribute(不恢復 InitializeComponent 方法的呼叫)
    並更改為 x:Class="WpfApplication1.MainWindowABC"

    程式依舊可以執行
    這時我們開啟IL Disassembler(中間語言反編譯器)
    發現專案編譯生成的程式集裡包含一個 MainWindowABC 的類

圖1
編譯後生成的 MainWindowABC 的程式碼看起來大致為

using System.Windows;
        using System.Windows.Controls;

        class MainWindowABC : Window
        {
            private Grid grid;

            public WindowABC()
            {
                grid = new Grid();
                this.Content = grid;
            }
        }
    最後,我們回到最初的程式碼

    你會問在 XAML 裡有 x:Class="WpfApplication1.MainWindow",在 MainWindow.xaml.cs 裡也聲明瞭 MainWindow 這個類,難道它們不會衝突嗎?
    我們發現 MainWindow 這個類在宣告時使用了 partial 關鍵字。
    使用 partial 關鍵字,可以把一個類分拆在多處定義,只要各部分程式碼不衝突即可
    這樣,XAML 解析成的類和 C# 檔案裡定義的部分就合二為一。

以上均為 《深入淺出WPF》 一書中的內容, 下方為個人的驗證以及感悟

    下邊我們通過一個例子來證明 partial 將 XANL 解析的類和 C# 中的類合併:

    下邊是Main.xaml的程式碼 (在原始xaml檔案里加一個Button控制元件)
        <Window x:Class="WpfApplication1.MainWindow"
                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                Title="MainWindow" Height="350" Width="525">
            <Grid>
                <Button Content="Button" Height="23" HorizontalAlignment="Left" 
                Margin="162,149,0,0" Name="button1" VerticalAlignment="Top" Width="75" />
            </Grid>
        </Window>
    下邊是Main.xaml.cs的程式碼(我們在類MainWindow類加一個 test 方法)
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
        using System.Windows;
        using System.Windows.Controls;
        using System.Windows.Data;
        using System.Windows.Documents;
        using System.Windows.Input;
        using System.Windows.Media;
        using System.Windows.Media.Imaging;
        using System.Windows.Navigation;
        using System.Windows.Shapes;

        namespace WpfApplication1
        {
            /// <summary>
            /// MainWindow.xaml 的互動邏輯
            /// </summary>
            public partial class MainWindow : Window
            {
                public MainWindow()
                {
                    InitializeComponent();
                }

                public void test() { 

                }
            }

        }
    編譯生成
    然後我們用反編譯器打開發財編譯生成的程式,  

圖2
我們發現裡邊有 button1控制元件 和 test 方法,證明了 partial的作用

(三)

    前邊(二)中我們只恢復 x:Class 這個 Attribute(不恢復 InitializeComponent 方法的呼叫)
    並更改為 x:Class="WpfApplication1.MainWindowABC"

    接下來我們做的例子是 繼續在上邊(二)中的程式碼裡做如下改動

        1.恢復 MainWindow.xaml.cs 裡 InitializeComponent 方法的呼叫

        2.在 WpfApplication1 中新建一個 WPF 視窗頁面,起名為 Window1,會生成一個Window1.xaml檔案和
        一個Window1.xaml.cs檔案

        3.將 Window1.xaml 中 x:Class 這個 Attribute 更改為 x:Class="WpfApplication1.MainWindow"

        4.去掉Window1.xaml.cs 裡的 InitializeComponent 方法

        5.在 Mainwindow.xaml 里加入一個 Button 控制元件

        6.在 Window1.xaml 里加入一個 Label 控制元件

    編譯執行,然後再反編譯器裡開啟  

圖3

    圖中我們看到 3 個類
        *   WpfApplication1.MainWindow
        *   WpfApplication1.MainWindowABC
        *   WpfApplication1.Window1

    我們看到 MainWindowABC 類裡有個 Button 控制元件和 InitializeComponent 方法
    MainWindow 類裡有個 Label 控制元件和 InitializeComponent 方法
    而Window1裡什麼也沒有

    疑問:

        Label 控制元件是在 Window1.xaml 裡新增,為什麼會出現在 MainWindow類裡?
        看一下 Window1.xaml 裡這句 x:Class="WpfApplication1.MainWindow"
        這讓你想到了什麼嗎?

    感悟1:
    --------------------------------------------------------------------------------------
    MainWindow.xaml.cs 裡 InitializeComponent 方法在呼叫的時候,
    會在所有 XAML 解析後生成的類中尋找 MainWindow 類,
    並將 XAML 解析生成的 MainWindow 類和 MainWindow.xaml.cs 生成的 MainWindow 類
    合併為一
    如果所有 XAML 解析後沒有 MainWindow 這個類就會出錯,就要去掉 InitializeComponent 方法的呼叫
    而想要 XAML 解析生成 MainWindow 類,就需要在某個 xaml 檔案裡新增
    x:Class="WpfApplication1.MainWindow" 才會生成相應的類
    ---------------------------------------------------------------------------------------


    感悟2:
    -----------------------------------------------------------------------------------------
    在(二)中的例子裡,最後生成兩個類 MainWindowABC 和 MainWindow,但是App.xaml裡啟動項仍是
    MainWindow.xaml。

    將 MainWindow.xaml 解析,生成了 MainWindowABC 這個類
    而 MainWindow.xaml.cs 在編譯的時候生成了 MainWindow 這個類
    所以最後有兩個類
    -----------------------------------------------------------------------------------------

以上均為個人見解,如有什麼錯誤或者偏差的地方,希望大家可以幫忙指出,我會及時改正