天天看點

WPF XAML X名稱空間詳解

X名稱空間裡面的成員(如X:Name,X:Class)都是寫給XAML編譯器看的、用來引導XAML編譯器将XAML代碼編譯為CLR代碼。

【X名稱空間裡面到底都有些什麼】

    x名稱空間映射的是:http://schemas.microsoft.com/winfx/2006/xaml,望文生義,它包含的類均與解析XAML語言相關,是以亦稱之為“XAML名稱空間”。

    與C#語言一樣,XAML也有自己的編譯器。XAML語言被解析并編譯,最終形成微軟中間語言儲存在程式集中。在解析和編譯XAML的過程中,我們經常要告訴編譯器一些重要的資訊,如XAML編譯的結果應該和哪個C#代碼編譯的結果合并、使用XAML聲明的元素是public還是private通路級别等等。這些讓程式員能夠與XAML編譯器溝通的工具就存在X:名稱空間中。

WPF XAML X名稱空間詳解
WPF XAML X名稱空間詳解

    我們注意到,它分為Attribute、标簽擴充、XAML指令元素三個種類。下面我們講講它們的具體用法:

【X名稱空間中的Attribute】

    前面我們已經講過,Attribute和Property是兩個層面上的東西,Attribute是語言層面上的東西,是給編譯器看的,Property是面向對象層面上的東西,是給程式設計邏輯看。而且一個标簽中的Attribute大部分對應對象的Property。在使用XAML程式設計的時候,如果你想給它加一點特殊的标記來改變XAML對它的解析,這時候就需要額外的給它添加一些Attribute了。比如,你想告訴XAML編譯器将哪個編譯結果和那個C#編譯的類合并,這時候就必須為這個标簽添加X:Class  Attribute來告訴編譯器。X:Class并不是對象成員,而是從X名稱空間裡拿出來硬貼上去的。讓我們浏覽一下常用的Attribute。

【x:Class】

    這個Attribute是告訴XAML編譯器将XAML編譯器編譯的結果和背景編譯結果的哪一個類進行合并,

使用x:Class有以下幾點要求:

這個Attribute隻能用于根節點。

使用x:Class的根節點的類型要與x:Class的值所訓示的一緻。

x:Class的值所訓示的類型在聲明的時候必須使用partial關鍵字。

x:Class已經在剖析最簡單的XAML的時候已經講過,在這就不多講了。

 【X:ClassModiffier】

    是告訴XAML編譯器由标簽編譯成的類具有什麼樣的通路級别。

使用這個Attribute的時候需要注意的是:

标簽必須具有x:Class Attribute。

X:ClassModiffier的值必須與X:Class所指定類的通路權限一緻。

X:ClassModiffier的值随背景代碼編譯語言的不同而有所不同。

例子:

<Window x:Class="WpfApplication4.wnd422"
        x:ClassModifier="internal"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="wnd422" Height="350" Width="525"/>           

對應的C#代碼:

/// <summary>
/// wnd422.xaml 的互動邏輯
/// </summary>
internal partial class wnd422 : Window
{
    public wnd422()
    {
        InitializeComponent();
    }
           
WPF XAML X名稱空間詳解

【X:Name】

    我們之前已經提過XAML是一種聲明式語言,但你是否想過XAML标簽聲明的是什麼呢?其實,XAML标簽聲明的是對象,一個XAML标簽對應着一個對象,這個對象一般是一個控件類的執行個體。在.NET平台上,類是引用類型。引用類型的執行個體一般都是以“引用者---執行個體”的形式成對出現的,而且我們隻能通過引用者來通路執行個體。當一個執行個體不在被任何引用者引用的時候,它将作為記憶體垃圾被銷毀。常見的引用者是引用變量,但不是唯一的。

X:Name的作用有兩個:

(1)告訴編譯器,當一個标簽帶有x:Name時,除了為這個标簽生成執行個體還要給這個标簽聲明一個引用變量,變量名就是x:Name的值。

(2)将XAML标簽所對應的Name屬性(如果有)也設定為x:Name值,并把這個值注冊到UI樹上,以友善查找。

【x:FieldModifier】

    使用了x:Name後,XAML标簽對應的執行個體就具有了自己的引用變量,而且這些引用變量都是類的字段,既然這樣就不免要關注一下它的通路級别。預設情況下這些字段的級别都被設定成了Internal。在程式設計的時候,有的時候需要用一個程式集裡的一個窗體元素通路到另一個程式集的窗體元素,那麼就需要使用x:FieldModifier來改變引用變量的通路級别!

    因為x:FidleModifier是引用變量的通路級别,是以要配合x:Name一起使用。否則沒有引用變量,何來引用變量通路級别。

例如:

<Window x:Class="WpfApplication4.wnd423"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="wnd423" Height="99" Width="438">
    <StackPanel>
        <TextBox x:Name ="_txtBox" x:FieldModifier="internal"  Height="23" Text="TextBox"/>
        <Button Content="OK" Click="Button_Click"/>
    </StackPanel>
</Window>           

對應的C#背景代碼:

public partial class wnd423 : Window
{
    public wnd423()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if(string.IsNullOrEmpty(_txtBox.Name))
        {
            _txtBox.Text = "No Name";
        }
        else
        {
            _txtBox.Text = _txtBox.Name;
        }
    }
}
           
WPF XAML X名稱空間詳解

【x:Key】

     最自然的檢索方式莫過于”key-value“的形式了。在XAML檔案中,我們可以把需要多次使用的内容提取出來放在資源字典中,需要使用的時候就用這個資源的key将這個資源檢索出來。

    x:key的作用就是為資源貼上用于檢索的索引。在WPF中,幾乎每個元素都有自己的Resource屬性,這個屬性就是“key-value”的集合。隻要把元素放進這個集合裡,這個元素就成了資源字典中的一個條目。當然,為了能檢索到這個條件,就必須為它添加x:Key。資源在WPF中非常重要,需要重複使用的XAML内容,如Style,各種Template和動畫都需要放在資源裡。

先讓我們看XAML代碼:

<Window x:Class="WpfApplication4.wnd425"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="wnd425" Height="152" Width="341">
    <Window.Resources>
        <sys:String x:Key="myString" x:Shared="false">Hello WPF Resources</sys:String>
    </Window.Resources>
    <StackPanel Background="LightSlateGray">
        <TextBox Height="23" Text="{StaticResource ResourceKey=myString}"/>
        <TextBox x:Name="_txtBox2" Height="23" Text="TextBox"/>
        <Button Content="OK" Click="Button_Click"/>
    </StackPanel>

</Window>           

    資源不但可以在XAML中使用,也可以在C#中通路,C#中使用如下方式:

_txtBox2.Text = this.FindResource("myString") as string;           

【x:Shared】

    學習x:key的時候我們已經了解到,如果把某個對象作為資源放入資源字典裡後我們就可以把它們檢索起來重複使用。那麼每當我們檢索到一個對象,我們得到的究竟是同一個對象呢,還是這個對像的一個副本呢?這就要看我們為x:Shared賦什麼值了。

    x:Shared一定要與x:Key配合使用,如果x:Shared值為true,那麼每次檢索這個對象的時候,我們得到的都是同一個對象,反之,我們得到的就是這個對象的一個副本。預設這個值是true。也就是說我們使用的都是同一個對象。

【x名稱空間下的擴充标簽】

    标記擴充實際就是一些MarkupExtension類的直接或間接派生類。x名稱空間中就包含一些這樣的類,是以稱其為x名稱空間标簽的标記擴充。

【x:Type】

    顧名思義,x:Type應該是一個資料類型的名稱。一般情況下,我們在程式設計中操作的資料類型執行個體或者執行個體的引用。但有的時候我們也需要用到資料類型本身。

    能讓程式員在程式設計的層面上自由的操作這些資料類型,比如在不知道具體類型的情況下建立這個類型的執行個體并嘗試調用它的方法,.NET命名空間裡還包含了名為Type的類作為所有資料類型在程式設計層面上的抽象。

    當我們想在XAML中表達某一資料類型就需要用到x:Type标記擴充。比如某個類的一個屬性,它的值要求的是一個資料類型,當我們在XAML中為這個屬性指派是就需要用到x:Type。請看下面這個例子:

我們先定義一個C#的MyButton:

class MyButton : Button
{
    public Type UserWndType { get; set; }

    protected override void OnClick()
    {
        base.OnClick();

        Window wnd = Activator.CreateInstance(UserWndType) as Window;
        if (wnd != null)
            wnd.ShowDialog();
    }
};
           

再建立一個名為wnd425的Window

在建立一個Window:

<Window x:Class="WpfApplication4.wnd431"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local ="clr-namespace:WpfApplication4"
        Title="wnd431" Height="162" Width="306"> 
    <StackPanel Background="LightSlateGray">
        <local:MyButton Content="OK" UserWndType="{x:Type TypeName=local:wnd425}"/>
    </StackPanel>
</Window>           

則運作結果如下:點選Ok時,彈出新的建立的wnd425的對話框。

WPF XAML X名稱空間詳解

【x:Null】

    在XAML裡面表示空值就是x:Null。

    大部分時間我們不需要為屬性附一個Null值,但如果一個屬性有預設值而我們有不需要這個預設值就需要用的null值了。在WPF中,Style是按照一個特定的審美規格設定控件的各個屬性,程式員可以為控件逐個設定style,也可以指定一個style目标控件類型,一旦指定了目标類型,所有的這類控件都将使用這個style----除非你顯示的将某個執行個體的Style設定為null。

請看下面的事例:

<Window x:Class="WpfApplication4.wnd432"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="wnd432" Height="309.231" Width="325.385">
    <Window.Resources>
        <Style x:Key="{x:Type Button}" TargetType="{x:Type Button}">
            <Setter Property="Width" Value="60"/>
            <Setter Property="Height" Value="36"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
    </Window.Resources>
    <StackPanel Background="LightSlateGray">
        <Button Content="OK"/>
        <Button Content="OK"/>
        <Button Content="OK"/>
        <Button Content="OK" Style="{x:Null}"/>
    </StackPanel>
</Window>           
WPF XAML X名稱空間詳解

【x:Array】

    通過它的item屬性向使用者暴露一個類型已知的ArrayList執行個體,ArrayList内成員的類型由x:Array的Type指明。下面這個例子就是把ArrayList做為資料源向一個ListBox提供資料:

由于x:Array的Items屬性是隻讀的,是以隻能通過标簽聲明文法添加資料值:

<Window x:Class="WpfApplication4.wnd434"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:WpfApplication4"
        Title="{x:Static local:wnd434.ShowString}" Height="300" Width="300">
    <ListBox Margin="5">
        <ListBox.ItemsSource>
            <x:Array Type="sys:String">
                <sys:String>Tim</sys:String>
                <sys:String>Tom</sys:String>
                <sys:String>Victor</sys:String>
            </x:Array>
        </ListBox.ItemsSource>
    </ListBox>
</Window>           
WPF XAML X名稱空間詳解

【x:Static】

    這是一個很常用的标記擴充,它的作用是在XAML文檔中使用資料類型為static的成員。因為XAML不能編寫邏輯代碼。是以使用x:Static通路的static成員一定是資料類型的屬性和字段。

    如果一個程式需要支援國際化,一般需要把顯示的字元串儲存在一個資源類的Static屬性中,是以支援國際化的程式UI中對x:Static的使用相當的頻繁。

【XAML指令元素】

XAML指令元素隻有兩個:

x:Code 

x:XData

    我們之前已經在代碼後置一節介紹過x:Code标簽,它的作用是可以在XAML文檔中編寫後置的C#背景邏輯代碼,這樣做的好處就是不需要把XAML和C#分放在兩個文檔中,這樣寫的問題是代碼不容易維護,不宜調試,一般沒有人願意這麼幹。

    x:XData是一個專用标簽。WPF把包含資料的對象稱為資料源,用于把資料源中的資料提供給資料使用者的對象被稱做是資料提供者,WPF中包含多種資料提供者,其中一個類名叫做XmlDataProvider執行個體,那麼XmlDataProvider執行個體的資料就要放在x:XData的标簽内容裡。

參考《深入淺出WPF》

繼續閱讀