程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF入門之XAML初窺

WPF入門之XAML初窺

編輯:關於.NET

Overview: 很早就想寫些文章來總結一下自己學習一些新知識的經歷,一來可以在日後查找,其到一個索引的作用;二來可以和愛好技術的朋友們共同交流,鑒於工作緣故始終無法抽身寫。最近源於對WPF和Silverlight的濃厚興趣和項目中要用的緣故,特此和大家分享一些學習WPF/Silverlight的過程。這個系列會簡單回顧一些WPF中基本的概念和入門知識,以此來構成創建WPF程序(甚至於Silverlight程序,其在很大程度上有些依賴於WPF)的基礎。本人不曾寫過很多blog,再者WPF本身對程序員的一些創新思維挑戰對我來說都是很大的難點,不周之處且請各位大俠指點。不勝感謝。

Topic: 本文為此系列的第一張,將大致介紹一下在.NET3.0中正式啟用的XAML的相關概念以及其在WPF中的應用。

總所周知,隨著.NET Framework 3.0的到來,其包含的幾個組件Windows Workflow Fundation, Windows Communication Foundation, Windows Cardspace以及我們要講的Windows Presentation Foundation逐漸吸引了大家很多的目光,作為.NET Framework的一部分,其提供了很多優越性而使得我們的編程模式以至變成思路都發生了很多的改觀。而在其最主要的幾個優點上,其引入的"聲明式描述"帶給我們煥然一新的感覺,而這就是XAML的主要功勞。XAML作為可以在很大程度上替代一些coding語句的聲明式XML,.NET Framework提供了對XAML的編譯支持,而這無非又讓我們看到了和HTML/XML很相似的風格,這種看似很隨意,很靈活的風格給我們帶來了新的編程體驗。WF, WPF都采用XAML來進行部分過程的描述。

1. 什麼是XAML?

XAML是一種相對簡單、通用的聲明式變成語言,它適合於構建和初始化.NET對象。它由一些規則和關鍵字構成,但是它自己沒有任何有意義的元素。在沒有WPF/WF框架的基礎上討論XAML就象在沒有.NET Framework的基礎上討論C#一樣是沒有任何意義的,因為它本身並不能提供任何有意義的元素,需要由WPF/WF框架或者說.NET XAML編譯器和WPF應用框架來承載、理解XAML的表達意義。由於XAML的通用性,實際上你可以把它應用於任何.NET技術。然而,是否在使用WPF時使用XAML是可選的,每一個XAML能做的事情完全可以由任何一種你喜歡的.NET語言來實現,但是反過來是不行的。在後邊的解釋中你會看到,實際上針對XAML的解釋,XAML編譯器是把XAML語句與.NET對象/類型聯系在一起的,將XAML納入和.NET類型相同的模型中控制是他們為什麼能夠互相兼容的重要原因。

例如如下的XAML片段和.NET C#語句所表達的結果是相同的:

XAML: <Button xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation Content="OK" />

C#:   System.Windows.Controls.Button btnOk = new System.Windows.Controls.Button();

b.Content = "OK";

2. XAML元素及特性2.1 XAML命名空間

XAML文件的跟對象元素必須至少有一個XML命名空間,用於驗證自己和其子元素。你可以在根元素或子元素上聲明額外的XML命名空間來標識你的自定義元素,但每個命名空間下的標識符都必須有一個唯一的前綴。我們把http://schemas.microsoft.com/winfx/2006/xaml/presentation作為默認(主要)的命名空間,我們在使用大多數控件時都使用此主命名空間,因為WPF通過硬編碼的方式將此命名空間與.NET的命名空間進行了映射。而對於次命名空間,我們通常需要添加前綴來表示其命名空間在以下范圍內被引用,中就像C#中的using System;一樣,聲明了一個可以引用的命名空間。以下代碼片段演示了如何使用主命名空間和次命名空間:

<UserControl x:Class="MediaPlayer.Page"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Width="450" Height="300">
  <Grid x:Name="LayoutRoot" Background="White">
    <TextBlock FontSize="12" FontWeight="Bold" HorizontalAlignment="Center">Vedio Player</TextBlock>
  </Grid>
</UserControl>

2.2 屬性元素(Property Element)

屬性元素本質上是為了增加在元素中包含子元素的一種方式。它是XAML提供的用來替代更加詳細的語法來設置屬性值的方法。例如:

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
  <Button.Content>
    </Rectangle Height="40" Width="40" Fill="Black" />
  </Button.Content>
</Button>

Content屬性現在被設置為一個XML元素而不是XML屬性,Button.Content中的句點用來區分對象元素與屬性元素。屬性元素總會以“類型名.屬性名”的形式出現並包含在“類型名”對象元素中。說白了,屬性元素是為了擴展某類型的屬性而存在的。

2.3 類型轉換器(Type Converter)

在XAML中實際上我們都是以String的類型來賦予各種屬性值的,但在對於.NET這樣的有類型庫來講,不是所有的屬性值都是為String的,比如對於Button的Background屬性,在C#中我們需要這樣來寫:

System.Windows.Controls.Button b = new System.Windows.Controls.Button();

b.Content = “OK”;

b.Background = System.Windows.Media.Brushes.White;

這段C#代碼等同於下邊的XAML代碼片段:

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Content="OK">
  <Button.Background>
White
</Button.Background>
</Button>

可以很容易的發現,在C#中Button的Background屬性對應的類型為System.Windows.Media.Brushes,而在XAML中由於無法具有強類型表現方式(當然它是通過另一種替代方式來表現的,只是表面上都是String)這裡選擇了用White這個字符串來表示我們想用White顏色來作為背景顏色。因為這個代碼片段是等同的,我們可以自然的將White字符串認為等同於System.Windows.Media.Brushes.White。而這個映射就是通過類型轉換器來實現的。這裡就通過BrushConverter和ColorConverter一起將White設置為Button的Background(因為Background實際上是Brush類型的)-而這些轉換器都是派生自TypeConverter的類。PS:這裡另一個參考就是我們在寫ASP.NET的自定義控件時裡邊都會有定義一些Converter,但他們是不一樣的。

其實以上的XAML代碼是簡化的寫法,更好的理解它我們可以寫為下邊這種方式(等價的):

<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Content="OK">
  <Button.Background>
<SolidColorBrush Color=”White” />
</Button.Background>
</Button>

而對應的C#代碼,為了更好的理解類型轉換器,我們改寫為下邊這種方式:

System.Windows.Controls.Button b = new System.Windows.Controls.Button();

b.Content = “OK”;

b.Background = (Brush)System.ComponentModel.TypeDescriptor.GetConverter(typeof(Brush)).ConvertFromInvariantString(“White”);

2.4 擴展標記

擴展標記就像類型轉換器一樣是用來擴展XAML的表達能力的,他們都可以在運行時計算字符串特性的值並生成合適的基於字符串的對象。但與類型轉換器不同的是,標記擴展是通過XAML的顯式的、一致的語法調用的,因此這是比較好的擴展XAML的方法。一般來講我們更多的把擴展標記應用於Resource, Binding等。如下邊的例子我們通常會用來標記當前元素/對象是使用的樣式(Resource):

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Simple Window">
<Window.Resources>
<SolidColorBrush x:Key="backgroundBrush">Yellow</SolidColorBrush>
<SolidColorBrush x:Key="borderBrush">Red</SolidColorBrush>
</Window.Resources>
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Background="{StaticResource backgroundBrush}"
BorderBrush="{StaticResource borderBrush}" Margin="5">
<Image Height="21" Source="zoom.gif"/>
</Button>
</StackPanel>
</DockPanel>
</Window >

2.5 集合項

XAML允許將項添加到支持索引的兩種類型的集合中:List和Dictionary.

List: 實現了System.Collections.IList接口的集合,它的Items屬性是實現了IList的ItemCollection類型;

Dictionary: 實現了System.Collections.IDictionary接口的集合,能夠支持在過程式代碼中添加、移除和枚舉鍵/值對。

下邊兩個例子展示了在XAML中如何應用集合項。注意:由於Content屬性實際上相當於在.NET對象中的默認屬性(例如在自定義控件中的默認屬性),所以可以將內容屬性的值作為此對象的直接子元素而不用Content屬性元素來標明,以此來簡化XAML的復雜度。

<ListBox xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation>
<ListBox.Items> <!—直接將子元素作為內容屬性—>
<ListBoxItem Content=”Item 1” /><!—等同於<ListBoxItem>Item 1</ListBoxItem>-->
<ListBoxItem Content=”Item 2” />
</ListBox.Items>
</ListBox>

3. 編譯XAML

XAML編譯 通常包括三項事情:將一個XAML文件轉換為一種特殊的二進制格式(BAML:Binary Application Markup Language);將轉換好的二進制資源嵌入到正在被創建的程序集中;然後執行鏈接操作將XAML和過程式代碼自動連接起來。

每個XAML都會在編譯過程中產生過程式代碼,這是在編譯過程中動態生成的,但這些過程代碼僅僅是“粘合代碼”Glue Code,類似於在運行時加載和解析松散XAML文件時所需要的代碼(和普通的Win Form自動生成的代碼用途類似),你可以在.g.cs(.g.vb)文件中找到這些代碼。

同樣你可以在XAML中混合使用過程代碼(Code inside),當XAML編譯後X:code元素中的部分將會放到部分類.g.cs文件中。

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml>
<Button Click=”button_Click”>OK</Button>
<x:Code><![CDATA[
Void button_Click(object sender, RouteEventArgs e)
{
this.Close();
}
]]></x:Code>
</Window>

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved