作者:David Chappell
Chappell & Associates
2006 年 9 月
適用於:
Windows Vista
Windows Presentation Foundation
Microsoft .NET Framework 3.0
摘要:Windows Presentation Foundation (WPF) 的首要目標在於協助開發人員建立吸引人又有效率的使用者介面,本篇文章將介紹 WPF 統一平台何以有助設計人員積極參與使用者介面的建立,並為獨立應用程式及瀏覽器應用程式提供一個共同的程式撰寫模型。(此文章包含連至英文網頁的連結,列印共 34 頁)
目錄
初步介紹 Windows Presentation Foundation
癥結所在
因應之道:Windows Presentation Foundation 之所能
使用 Windows Presentation Foundation
Windows Presentation Foundation 所採用的技術
運用 Windows Presentation Foundation
Windows Presentation Foundation 的工具
開發人員工具:Visual Studio
設計人員工具:Expression Interactive Designer
Windows Presentation Foundation 與其他的 Microsoft 技術
Windows Presentation Foundation 和 Windows Form
Windows Presentation Foundation 和 Win32/MFC
Windows Presentation Foundation 和 Direct3D
Windows Presentation Foundation 和 AJAX/"Atlas"
Windows Presentation Foundation 和 "WPF/E"
結論
作者簡介
初步介紹 Windows Presentation Foundation
一般來說,技術人員關心的多半只是技術。許多軟體專業人士對應用程式的運作方式比對應用程式與使用者的互動方式的興趣還大,可是對於花錢的大爺們來說則不然,使用者還是相當在意使用者介面。應用程式介面是整個軟體使用經驗的主要部分,對使用者來說,其實就等於 應用程式經驗。更好的介面有助於提昇使用經驗,進而促進生產力、有助建立客戶忠誠度,而且能拉動網站或其他等銷售業務。
以往使用者覺得純粹以文字為基礎的介面已經足夠,然而是他們現在已經習慣了圖形介面。隨著使用者介面的需求日益翻新,再加上圖形與媒體的廣泛應用,伴隨著網路的因素,因此大家自然期望與軟體的互動簡單容易。人們花越多時間與應用程式互動,應用程式的介面就越為重要。為了不負這日益顯著的期望,用於建立使用者介面的技術也必須向前邁進。
Windows Presentation Foundation (WPF) 的目標就是為 Windows 提供這些先進的技術。WPF 是 Microsoft .NET Framework 3.0 的一部分,能建置整合了文件、媒體、平面圖形、立體圖形、動畫、網路和其他等特色的介面。它和 .NET Framework 3.0 其他的內容一樣,將可用於 Windows Vista、Windows XP 和 Windows Server 2003,預計與 Windows Vista 同步上市。本篇文章將介紹 WPF,說明它的各種組件。文章主旨是要闡明此技術所能解決的問題,並探討 WPF 提供的解決方案。
癥結所在
假設有一家醫院想建立一個新的應用程式,以供體檢和追蹤病情之用。這個新應用程式的使用者介面的需求如下:
- 顯示與病人相關的影像與文字。
- 顯示和更新平面圖形,來顯示病人的生命跡象,例如心跳速度和血壓。
- 以立體檢視和重疊方式顯示病人資訊。
- 呈現超音波視訊或其他診斷結果,可能還能讓醫師或護士加上附註。
- 允許醫療人員讀取文件上有關病人或其狀況的附註,並允許他們在文件中加註。
- 在作為 Windows 應用程式 (讓醫院全體員工使用) 之際,亦可當成有安全性限制的網路瀏覽器應用程式 (讓遠端醫師透過網際網路進行有限存取)。
上述需求看似難度很高,但其實不是無理的要求。使用者介面要能適時地以合宜的方式呈現正確資訊,才會有高度的商務價值。以這裡所述的醫療情況為例,使用者介面甚至攸關著拯救生命。即便是比較不那麼迫切的情況,例如以線上商務等以消費為主的應用程式,優質的使用經驗依然有助於區別公司產品,使競爭對手相形失色,進而提高銷售量和公司的品牌價值。總而言之,許多的現代化應用程式介面如果能整合圖形、媒體、文件等其他現代化使用經驗的元素,必定獲益非淺。
以 2006 版的技術在 Windows 上建立這種介面是可以辦得到的,不過挑戰性極高,其中可能遇到的主要障礙如下:
- 今日的圖形、影像和視訊在應用上牽涉到多種不同的技術,要尋找能駕馭這些多樣化技術的開發人員,就和維護所建立的應用程式一樣難度頗高且代價不斐。
- 要想設計出能夠將這些功能完全呈現給使用者的介面,是一項高度的挑戰。參與的人員必須為專業的設計人員 (光是軟體開發人員並不具備適當的技能)。此外,設計人員與開發人員很難攜手緊密合作,尤其是設計這種全方位功能介面的時候,更是困難。
- 要想提供全方位功能介面,用作獨立 Windows 桌面應用程式且亦作為瀏覽器裝載版本,需要採用兩套技術分別建置兩套實作。Windows 桌面應用程式很可能使用 Windows Form 以及其他原生的 Windows 技術,而瀏覽器裝載應用程式則要使用 HTML 和 JavaScript。因此這兩個開發小組所需具備的技能也是截然不同。
建立功能強大且現代化的使用者介面不應該是件複雜的工程,只要有一個共同的基礎就能因應這些挑戰,讓開發人員不僅有統一的方式可以援用,也讓設計人員扮演舉足輕重的角色。這正是 WPF 的用意,現在我們就來看看如何做到這一點。
因應之道:Windows Presentation Foundation 之所能
WPF 所提供的功能中有三個最為重要,它們分別是:一個能供現代化使用者介面使用的統一平台,讓開發人員與設計人員攜手合作的能力,以及一種能供 Windows 和網頁瀏覽器使用者介面使用的共同技術。在這一小節,我們就來研究一下這三個功能。
一個能供現代化使用者介面使用的統一平台
在還沒發明 WPF 之前,要想建立前述的 Windows 使用者介面需要用到幾個不同的技術,大致情況如下表所示。
| |
Windows Form |
PDF |
Windows Form/ GDI+ |
Windows Media Player |
Direct3D |
WPF |
| 圖形介面,例如表單和控制項 |
X |
|
|
|
|
X |
| 螢幕巡覽式文件 |
X |
|
|
|
|
X |
| 固定格式文件 |
|
X |
|
|
|
X |
| 影像 |
|
|
X |
|
|
X |
| 視訊與音訊 |
|
|
|
X |
|
X |
| 平面圖形 |
|
|
X |
|
|
X |
| 立體圖形 |
|
|
|
|
X |
X |
要建立表單、控制項和 Windows 圖形使用者介面的其他部分,開發人員很有可能選擇 Windows Form,而這是 .NET Framework 的一部分。如果介面需要顯示文件,Windows Form 能支援一些螢幕巡覽式文件,而固定格式文件則會使用 Adobe PDF。至於影像和平面圖形,開發人員會使用 GDI+,這種特殊的程式設計模型也可透過 Windows Form 來使用。若要顯示視訊和音訊,則可能要端賴 Windows Media Player,而立體圖形則要用到標準的 Windows 組件 Direct3D。
這種複雜的情形,純粹是因為過去的種種而導致的,實在一點都不合理。真正合理的方法,是提供單一的統一解決方案:WPF。為已裝有 WPF 的電腦建立應用程式時,開發人員將可能使用它來解決上述所有問題,畢竟,比起採用多種獨立技術來建立使用者介面,使用一個一貫的基礎不是很好嗎?
當然啦,WPF 並不會因此就取代表中的任何一種技術,Windows Form 應用程式仍有其價值所在,因為即使是在有了 WPF 的新紀元,一些新的應用程式還是會繼續使用 Windows Form (在此特別一提,WPF 能夠與 Windows Form 交互操作,文章稍後將詳加說明)。Windows Media Player 會繼續扮演它獨立的角色,PDF 文件也會繼續被使用,而 Direct3D 在遊戲和某些種類的應用程式裡也仍為一項重要的技術 (實際上,WPF 本身需要依賴 Direct3D 進行轉譯)。
不過,WPF 在單一技術裡提供廣泛的功能,大幅簡化現代化使用者介面的建立工作。下面是一個以 WPF 為基礎的健保應用程式可能呈現給使用者的典型螢幕,現在就讓我們來體驗一下這個統一的方式:

[圖 1] WPF 介面能綜合影像、文字、平面圖形、立體圖形和其他等更多元素。
螢幕中所包含的元素有文字、影像以及二維和三維的圖形,只要使用 WPF 就能產生所有這些元素,開發人員無須使用諸如 GDI+ 或 Direct3D 等特殊繪圖技術撰寫程式碼。同樣地,WPF 可允許影像的顯示與加註,像是下圖所示的超音波影像。

[圖 2] WPF 介面能夠包含影像,允許使用者加註文字。
WPF 亦能以方便閱讀的方式顯示文件。以醫院用的應用程式為例子,醫師可能能夠查看與病人治療有關的附註,或是存取與某個主題有關的最新醫療病例。而醫師也能自行加上附註,如下圖所示。

[圖 3] WPF 介面能夠顯示含有多個欄位的文件,其中也包括附註。
請注意,文件是顯示在方便閱讀的欄位中,使用者一次可以移動一個頁面而不是以捲動的方式顯示接下來的內容。螢幕巡覽式文件的可讀性的確值得投注精力加以改善,而這也是 WPF 的一個重要目標。雖然螢幕巡覽式文件十分好用,但是有時固定格式文件才是最佳選擇;因為無論是螢幕版本或是列印版本,固定格式文件的版面在各種情況下均一致。為了能定義這種類型的文件,Microsoft 建立了 XML Paper Specification (XPS)。WPF 也提供一組應用程式發展介面 (Application Programming Interface,API),供開發人員建立和使用 XPS 文件。
然而,建立現代化使用者介面意味的不只是統一以往多樣的技術,還需要善用現代化繪圖卡,因此 WPF 盡可能卸除工作,採用系統內可用的繪圖處理器單元 (GPU)。此外,現代化介面不應再受制於點陣圖的有限功能,因此 WPF 全面採用向量圖形,讓影像能按呈現螢幕的大小和解析度自動調整,開發人員無須為小型螢幕和大型電視螢幕分別建立圖形,只要交給 WPF 自動處理就行了。
WPF 藉由統一所有將使用者介面建置成單一基礎所需的技術,大幅簡化了這些介面的建置工作。由於參與這些工作的人員只須學習一個環境,WPF 能縮減應用程式的建立和維護成本。再者,WPF 使得整合介面 (圖形、視訊和其他等元素) 的建置輕鬆容易,得以改進使用者與 Windows 應用程式互動的品質與商務價值。
讓開發人員與設計人員一同合作的能力
提供一個統一的技術基礎以建立全方位功能使用者介面是一件好事,可是若想要開發人員能善用此種強大的基礎,建立完整又容易使用的介面,這個要求可能就太高了。建立優質的使用者介面,尤其是像上述的醫院範例那樣全面的介面,所需的通識技能往往是多半的軟體專業人士所不具備的。儘管許多應用程式根本未採用那些技術,要想建置優良的使用者介面,就必須與專業介面設計人員一同合作,這是個不爭的事實。
設計人員和開發人員究竟如何能攜手合作呢? 其實,現今兩者所採用的互動方式並不妥當。最常見的方法是設計人員使用繪圖工具,來建立應用程式所該顯示的螢幕版面配置靜態影像,然後把這些影像交給負責建立程式碼以進行實作的開發人員。對設計人員而言很容易就繪製而成的影像,對開發人員來說可能難以甚至不可能加以實作。開發人員可能因為技術上的限制、緊迫的時間、技術的缺乏、誤解甚或是根本就不同意設計構思,而無法徹底落實設計人員的構想。而這裡所需的是一個更好的途徑,讓相依的兩方既能夠攜手作業又不影響介面品質。
為了實現這個方法,WPF 於是引進了 eXtensible Application Markup Language (XAML)。XAML 定義一組 XML 項目 (例如 Button、TextBox、Label 和其他許多項目),來明確定義使用者介面的外觀。XAML 項目通常也具有屬性,能供設定多種選項,舉例而言,下列的簡短 XAML 能建立具有 "No" 文字的紅色按紐:
<Button Background="Red">
No
</Button>
每個 XAML 項目都各自對應到一個 WPF 類別,而該項目內的每個屬性 (Attribute) 在該類別裡都有一個對應的屬性 (Property) 或事件。舉例而言,使用下列 C# 程式碼亦可產生同一個紅色按鈕:
Button btn = new Button();
btn.Background = Brushes.Red;
btn.Content = "No";
如果在 XAML 裡可以表示的東西亦可用程式碼表示 (事實的確如此),XAML 又有何價值呢? 答案是,比起撰寫程式碼從頭開始,建置能產生和取用 XML 描述的工具簡單多了。由於使用 XAML,能更容易使用工具來描述使用者介面,因此開發人員和設計人員能夠輕鬆合作。整個程序如下圖所示。

[圖 4] XAML 協助設計人員和開發人員攜手合作
設計人員可使用諸如 Microsoft Expression Interactive Designer 的工具,指明使用者介面的外觀與互動性能,該工具是以 WPF 介面的外觀和功能為導向,會利用 XAML 來表示介面描述 (雖然它可能包含類似此範例中的簡單按鈕,可是這個描述事實上比上面一小段程式碼還複雜許多)。之後,開發人員將那個 XAML 描述匯入像是 Microsoft Visual Studio 的工具中,完全採用介面定義,而不是以設計人員所產生的靜態影像為基礎,從頭著手重新建立。接下來,開發人員撰寫介面的程式碼 (像是事件處理常式) 以及應用程式所需的其他功能。要想建立能全域套用到應用程式介面且又能依情況進行自訂的樣式,也是可行的。
讓設計人員和開發人員如此一同工作,能減少知識轉移所導致的錯誤,此類錯誤通常是在開發人員依照設計人員的影像進行介面實作時發生的。如此還可允許他們雙方平行作業,加快重複項目的製作速度,以更好的方式反應意見。又因為這兩種環境使用同樣的建置系統,因此可在這兩個開發環境之間來回傳遞 WPF 應用程式。除此,還有更專業的工具能供設計以 XAML 定義的介面,例如 Electric Rain 的 ZAM 3D 就能用來建立立體的介面元素。
比較良好的使用者介面能夠提高生產力,它們的商務價值是可預見的。不過,要建立真正有效率的介面,尤其是 WPF 所提供的多個層面,整個程序就必須以設計人員為重。XAML 的首要目標以及支援這個概念的那些工具就能真正實現這一點。
能供 Windows 和網頁瀏覽器使用者介面使用的共同技術
為 Windows 應用程式建立有效的使用者介面十分重要,而為以 Web 為基礎的應用程式建立有效的使用者介面,重要性不下於前者。根據預設,這些介面是透過網頁瀏覽器提供的,最簡單的方法就是讓瀏覽器被動地顯示所接受到的 HTML。而回應性比較高的瀏覽器介面則提供以 JavaScript 執行的邏輯,可能使用非同步 JavaScript 和 XML (AJAX)。此種介面甚至還支援動畫、視訊和其他元件,使用 Adobe Flash Player 或它種技術,能提供此種全方位功能介面的 Web 軟體,有時亦稱為豐富型網際網路應用程式,能大幅改善使用經驗,還可新增實質的商務價值,提高 Web 應用程式吸引使用者的能力。
在以往,建置這種介面所需用到的技術與建置原生 Windows 介面截然不同,因此,開發人員大多只專注於一種方法:全心扮演 Windows 介面開發人員,或是網頁介面開發人員的角色。可是如果要從 Windows 裡存取的豐富型網際網路應用程式,此時又該如何面對這種二選一的局面? 為何原生 Windows 介面和網頁瀏覽器式的介面就不能採用同樣的技術呢?
WPF 就能做到這一點。開發人員能夠使用 WPF 來建立 XAML Browser Application (XBAP),使它在 Internet Explorer 中執行。事實上,同樣的程式碼可以建立出獨立的 WPF 應用程式以及 XBAP。以下圖為例,圖中是一個金融服務的應用程式,它是獨立的 Windows 應用程式。它混用了文字、影像及各種圖形,就和前面舉的的醫院應用程式一樣 (此圖也示範了 Windows Vista 桌面,裡面包括一個時鐘和 Aero 主題,後者在應用程式視窗周圍以半透明方式顯示邊界)。

[圖 5] 金融服務應用程式能作為獨立的 WPF 應用程式來執行。
下面就是這個介面在 Internet Explorer 中以 XBAP 形式執行的樣子:

[圖 6] 相同的程式也可能用作為 XBAP 來執行。
現在,介面是受到瀏覽器框架 (Framed),而不是在自己的視窗內執行,不過它的功能不變。由於同一套程式碼在兩種情況下都適用,因此無須分別為兩種介面撰寫程式碼,進而減少所需的工作時數。而使用同樣的程式碼也表示使用相同的開發人員技能。WPF 不會迫使開發人員面臨要成為 Windows 介面開發人員還是網頁介面開發人員的難題,因為它允許在兩種不同的情況下運用相同的知識,所以能夠解決這種分歧的問題。
另一個對 Windows 介面和網頁介面採用相同技術的好處,就是應用程式建立者無須被迫在事前先決定應用程式應該採用哪種介面。只要目標用戶端符合 XBAP 的執行需求,應用程式即可以相同程式碼 (大部分的程式碼),提供 Windows 介面或是網頁介面。
因為 XBAP 是在需要時才從 Web 伺服器下載的,與獨立的 Windows 應用程式相較之下,它的安全性需求顯得比較嚴格。所以,XBAP 是在 .NET Framework 的程式碼存取安全性所提供的安全性沙箱裡執行,此外,它只在裝有 WPF 的 Windows 系統上與 Internet Explorer 6 搭配執行。然而,現在對於符合這些需求的應用程式而言,豐富型網際網路應用程式採用同樣的基礎作為獨立的 Windows 應用程式。
使用 Windows Presentation Foundation
瞭解 WPF 能解決何種問題相當有用,但瞭解它究竟如何解決那些問題,也是相當實用的知識。本節中,我將探討 WPF 技術的本身,然後討論它們在 Windows 桌面應用程式、XBAP 和 XPS 文件中個種不同的運用方式。
Windows Presentation Foundation 所採用的技術
雖然 WPF 提供統一基礎來建立使用者介面,我們可分開探討它所包含的各項技術。這些組件包括文件、影像、圖形、動畫和其他等等。可是這些所有組件均端賴 WPF 的基本應用程式模式,我們現在就來看看。
應用程式模型
WPF 和其他的 .NET Framework 組件一樣,是以一組命名空間來組織功能,將全都的功能都包含在 System.Windows 命名空間裡面。無論它使用該功能的哪個部分,每個 WPF 應用程式的基本結構都大同小異。不管是獨立使用的 Windows 應用程式或是 XBAP,應用程式通常都是由一組 XAML 頁面和與其相關的程式碼所構成的。
每個應用程式的根項目均繼承 WPF 的標準 Application 類別,此類別提供對每個應用程式都實用的通用服務,其中包括持有著整個應用程式都能使用的狀態,以及提供標準的方法,例如啟動應用程式的 Run 和結束應用程式的 Shutdown。
要建立 Application 物件,可利用 XAML 透過 Application 項目來進行,亦可使用 Application 類別進行程式撰寫 ( WPF 裡的所有東西幾乎都如此,但為了簡單起見,本文一律使用 XAML 選項)。下面是一個簡單的 XAML 範例:
<Application xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Page1.xaml"
x:Class="Example.SimpleApp">
. . .
</Application>
這個定義首先先將 WPF 的命名空間指明為這個項目的預設,然後再定義 XAML 命名空間的前置詞 (XAML 被用的頻率比 WPF 還高,這兩個命名空間並非同意字)。接下來,它使用 StartupUri 屬性來指示在啟動應用程式時應載入和顯示的 XAML 頁面其名稱。最後的屬性是 Class,它是用來識別含有與此 Application 有關的程式碼之類別。前面說過,WPF 應用程式通常含有 XAML 以及 C# 或 Visual Basic 的程式碼,所以會將這個類別的程式碼放在一個程式碼後置 檔案裡面。Application 開頭標記之後就是用來定義這個應用程式的所有 XAML,我在此並沒列出,過來就是 Application 項目的結尾標記。
隨然所有的 WPF 應用程式都是從同樣的根類別衍生而來,但是開發人員仍有一些重要的抉擇要考慮,其中一個就是應用程式究竟要提供傳統的對話方塊式介面,還是巡覽式介面。對話方塊式介面提供的是按鈕以及每位 Windows 使用者都熟悉的其他元素;反之,巡覽式介面則提供瀏覽器相關的活動,舉例而言,若有一個對話方塊,它會載入新的頁面,而不會開啟新的視窗。此類的介面實作為一組頁面,每個頁面都是由以 XAML 定義的使用者介面以及某個程式語言的邏輯表示所構成的。XAML 提供一個能用來將頁面連結在一起的 Hyperlink 項目,和 HTML 定義的瀏覽器頁面相同。使用者透過這些頁面進行巡覽,就好比透過以網路為基礎的應用程式一樣,端賴歷程記錄清單來移動。但是您可別搞混喔,這個仍舊是一個 Windows 應用程式。XBAP 通常會採用這種介面;獨立的 Windows 應用程式絕對可以透過巡覽介面與使用者互動的,只是看建立應用程式的人如何抉擇而已。
無論應用程式使用何種介面樣式,通常會顯示一個或多個視窗,在這一方面,WPF 提供幾種方式以供使用。簡單的 Window 類別提供基本視窗功能,像是視窗的顯示、隱藏和關閉,此類別通常是不採用巡覽介面的 WPF 應用程式在使用的。NavigationWindow 是給採用巡覽式介面的應用程式使用的,它加入巡覽支援來擴充基本的 Window 類別。這個支援包括一個 Navigate 方法,允許應用程式移動到一個新的頁面、一個追蹤使用者巡覽記錄的日誌檔以及多種與巡覽相關的事件。
版面配置與控制項
WPF 應用程式使用面板 (panel) 來配置和組織介面的各個組件。每個面板都能有子系,包括像是按鈕或文字方塊等控制項 以及其他面板。不同種類的面板所提供的版面配置選項亦所有差異,現在我來舉些例子:DockPanel 能將子系項目放置於版面的邊緣;Grid 則恰如其名,可以將它的子系準確地放入方格中,方法是,開發人員定義一些方格資料行與資料列,然後指明要將子系放置於何處;至於 Canvas,開發人員可用它將它的子系任意放置在面板邊界某一個地方。
WPF 和其他使用者介面技術一樣,提供了一大組的控制項,並允許開發人員恣意建立自訂的控制項。一組標準的控制項包括 Button、Label、TextBox、ListBox、Menu、Slider 等其他傳統的使用者介面設計元素。WPF 也提供比較複雜的控制項,例如 SpellCheck、PasswordBox 以及能與 Ink (即 Tablet PC) 搭配使用的控制項等等。
通常在圖形介面中,使用者所產生的事件 (例如移動滑鼠和按下按鍵) 都可由 WPF 應用程式的控制項來處理,雖然控制項和其他的使用者介面項目能以 XAML 來指定,可是事件就非得利用程式碼來處理不可。舉例來說,下面是某個 Canvas 上一個簡單的 Button 的 XAML 定義:
<Canvas xmlns=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Example.CodeForCanvas">
<Button Click="Button_Click">
按此處
</Button>
</Canvas>
Canvas 開頭標記一開始定義了 WPF 和 XAML 命名空間,接著指明與此 XAML 有關的程式碼可於 CodeForCanvas 的類別中找到,而這個類別是包含於 .NET Framework 命名空間 Example 裡面。然後,再定義 Button 本身,指明以「按此處」為螢幕上的文字。Button 的開頭標記中有個 Click 屬性,它指明這個按鈕要利用 Button_Click 方法來處理 Click 事件,而那個方法的程式碼如下:
namespace Example {
public partial class CodeForCanvas : Canvas {
void Button_Click(object sender, RoutedEventArgs e) {
Button btn = e.Source as Button;
btn.Background = Brushes.Purple;
}
}
}
這裡的命名空間與類別名稱均符合剛才 Canvas 標記中所指明的,CodeForCanvas 類別繼承於 WPF 所提供的基底 Canvas 類別,而且被定義成部分類別。部分類別是 .NET Framework 2.0 的新增類別,它們能將個別定義的程式碼整合成一個類別。在這個範例中,XAML 定義的 Canvas 產生一個部份類別,此類別會與這裡所示的部分類別整合為一,產生一個完整的類別,既能顯示帶有按鈕的畫布,又能處理它的事件。
CodeForCanvas 類別裡面會提供要處理那個事件的 Button_Click 方法,雖然事件的引數是利用 WPF 定義的 RoutedEventArgs 類別來傳遞,但事件仍遵守一般的 .NET Framework 事件慣例。此類別的 Source 屬性含有一個參照,指向先前產生該事件的 Button,而該方法就是用它把按鈕的顏色變為紫色的。
正如這個簡單範例所示,在組織 WPF 使用者介面裡的元素時是採用視覺化樹狀結構。在這個範例中,樹狀結構裡只有一個具有單一子系 Button 的 Canvas,但是一個實際的 WPF 應用程式裡的樹狀結構,則複雜許多。要想真正建立螢幕巡覽式介面,就得轉譯這個視覺化樹狀結構。在可能的情況下,WPF 依賴硬體進行轉譯,讓裝有應用程式的電腦裡的繪圖卡來處理這個工作,如果電腦的繪圖硬體無法勝任這個工作,WPF 就會使用它自己的軟體來轉譯介面;WPF 會在執行階段作出適當的決定,開發人員無須進行任何工作。
無論是使用硬體或軟體進行轉譯工作,WPF 都需要依賴保留模式 (retained mode) 的繪圖方式。應用程式的建立者定義視覺化樹狀結構的外觀,通常是混合使用 XAML 和程式碼。之後,WPF 自己會在這個樹狀結構中保留這項資訊。比方說,使用者在顯示視窗時,WPF 會自行處理,並不會要求應用程式重新繪製整個視窗或部分的視窗。由於組成樹狀結構的元素是以物件的形式儲存,而非螢幕上的像素,所以 WPF 具有足夠的資訊來應付此類的轉譯作業。就算 WPF 的視窗和控制項的大小被重新調整,它可以自行全部重新轉譯,原因是,它瞭解圖形的格式 (直線、橢圓形或其他等),而且採用的是向量圖形而非像素圖,因此有足夠的資訊根據新的大小重新繪製介面。
樣式與範本
如果有一種功能可允許在定義完使用者介面之後,反覆套用那個外觀,那一定非常實用,舉個例子,像階層式樣式表 (CSS) 就能讓您在 HTML 頁面中進行此類工作。WPF 具有類似的功能,它是利用樣式 來實作。從 CSS 樣式表受歡迎的程度,不難得知樣式定義相當實用。它們能將設計人員和開發人員區分開來,讓設計人員建立一致的介面外觀,開發人員一點都無須操心。
建立 WPF 應用程式的人員使用 XAML 的 Style 項目,能定義一或多種外觀,然後重複使用。舉例來說,名為 ButtonStyle 的樣式就可能定義如下:
<Style x:Key="ButtonStyle">
<Setter Property="Control.Background" Value="Red"/>
<Setter Property="Control.FontSize" Value="16"/>
</Style>
所有用這樣是定義出來的 Button 都是紅色背景,且字型大小為 16 級,例如:
<Button Style="{StaticResource ButtonStyle}">
按此處
</Button>
根據範例中的 "StaticResource" 外觀所示,WPF 樣式通常是定義成 Resource,而它只是應用程式程式碼中個別定義的資料。
樣式的能力所及不僅止於這個簡單範例所示,例如,一個樣式可以衍生自另一個樣式,它能繼承於該樣式或將之覆寫。樣式還可定義負責指定互動行為中共同部分的觸發程序。舉例來說,某個樣式可能指定當滑鼠暫留在按鈕上方時,按鈕會變成黃色。
WPF 也支援範本 的使用;範本與樣式很相似,而範本分為兩種:
- 資料範本:允許使用 XAML 的 DataTemplate 項目來指定一組特色,指明如何顯示資料。在資料範本中定義一次顏色、對齊方式其他等特色後,即可在應用程式使用者介面的其他地方套用。
- 控制項範本:允許使用 XAML 的 ControlTemplate 項目來定義控制項的外觀。
提供應用程式建立者一種簡單的方法來定義介面外觀,是一件相當合邏輯的事,而 WPF 的樣式和範本就是背後主要的機制。
文字
大多數的使用者介面多少會顯示一些文字,但對多數的人而言,閱讀螢幕上的文字和列印文字是兩回事,我們都習慣了書籍雜誌中的高品質文字呈現及文字間的關係,在閱讀螢幕上的文字時,感覺就是不同,總覺得那些文字的可讀性很低。
WPF 以縮減兩者間的差距為目標,盡可能讓螢幕上的文字具有和書面文字一樣的可讀性。為了達到此目的,WPF 支援業界標準的 OpenType 字型,允許使用現有的字型庫。它還支援最新定義的 ClearType 技術,這個技術透過子像素定位 (這種技術可以使現代化顯示螢幕上組成每個像素的子像素個別亮起),使得文字看起來更順眼。WPF 亦提供低階支援,透過 Glyphs 類別轉譯文字,這個類別是供 XPS 文件呈現字元之用,文章稍後會予以介紹。
為了進一步改善可讀性,WPF 還允許其他功能,例如連音符號,也就是以單一連結影像取代一組字元。舉例而言,"ffi" 這個字組在書面顯示中,通常會被含有這三個字元的單一連結連音符號所取代。在螢幕文字上加入這個符號,能提供更舒適的閱讀經驗,雖然他們可能不會意識到這些細節。
文件
由於使用者介面上有許多地方都會用到文字,因此改善可讀性可帶來正面效果。而我們多半會注意到文字的場合,就是在閱讀一大串文字的時候,例如閱讀文件。所以,螢幕文字可讀性的改善也牽涉到文件顯示方式的改進,WPF 就為此而支援兩種文件:固定 (Fixed) 文件和流動 (Flow) 文件。
固定文件在螢幕上和書面上看起來一模一樣。對某些表單、法律文件等它種出版而言,瞭解到文件外觀保持一致是很重要的一點,所以固定文件在某些領域的重要性不容忽視。WPF 支援的固定文件是由 XPS 所定義的,本文稍後會詳加說明。固定文件的內容可用 XAML 的 FixedDocument 項目來指明,這個簡單的項目只包含一個 PageContent 項目清單,每個項目裡含有固定文件中的某個頁面名稱。為了顯示固定文件,WPF 提供 DocumentViewer 控制項,它以唯讀方式顯示 XPS 文件,讓讀者能在文件中前後移動、搜尋文字或進行其他工作。
固定文件適用於螢幕與書面,而流動文件只適用於在螢幕上顯示。為了盡可能提高流動文件的內容可讀性,這些文件可以調整文件的文字,而圖形是按視窗大小與其他要素來顯示的。您可能已經猜到,流動文件是利用一個叫做 FlowDocument 的 XAML 項目進行定義的,範例如下:
<FlowDocument
ColumnWidth="300"
IsColumnWidthFlexible="True"
IsHyphenationEnabled="True">
<Paragraph FontSize="12">
<Bold>描述 WPF</Bold>
</Paragraph>
<Paragraph FontSize="10">
WPF 是用於 .NET Framework 3.0 的使用者介面技術。
它為現代化使用者介面提供統一的基礎,包括支援
文件、平面圖形、立體圖形、媒體等等。它也
允許適用同樣的方式 (以及同樣的程式碼) 來
建立獨立 Windows 應用程式以及在瀏覽器內
執行的應用程式。
</Paragraph>
</FlowDocument>
這個文件要求被顯示在一個寬不超過 300 的欄位中 (寬度是以與裝置無關的像素 來測量的,每一個單位定義為 1/96 英吋)。下一行程式碼中,文件建立者將 IsColumnWidthFlexible 屬性設為 True,指明寬度是可以調整的,如此一來,WPF 就能變更將用來顯示這份文件的欄位寬度和欄位數目。例如,使用者變更顯示此文件的視窗的寬度,WPF 能增加或減少用來顯示文件內容的欄位數目與欄位寬度。
接下來,文件要求將 IsHyphenationEnabled 屬性設為 True,以啟用斷字功能,之後則是文件中的兩段文字。每段文字都是包含在一個 Paragraph 項目裡,而且每段的字型大小設定都所有不同。第一段文字還指出它應該採用粗體字。
WPF 定義其他更多的 FlowDocument 選項,來提升可讀性。舉例來說,IsOptimalParagraphEnabled 屬性設為 True 時,WPF 會盡可能地在整個段落中平均分散空白處,如此能防止因空白行「氾濫」而影響到可讀性,這種做法在書面文件裡很常見。流動文件也可允許加註,例如在一般文字中或是在 Tablet PC 的 Ink 中加上附註。每個附註都是由一個錨點 和一個 Cargo 所構成;錨點會識別附註該與文件內的什麼內容相關連,而 Cargo 則含有附註本身的內容。
為了顯示 FlowDocument,WPF 包含了幾個不同的控制項,它們是:
- FlowDocumentPageViewer:允許在文件裡一次移動一頁。這個控制項提供前進和退後的按鈕,也有縮放控制項,使用者可以調整正在閱讀的文件的大小。
- FlowDocumentScrollViewer:提供比較傳統的 FlowDocument 捲動檢視,並在頁面右邊放置一個捲軸。
- FlowDocumentReader:綜合 FlowDocumentPageViewer 和 FlowDocumentScrollViewer 的功能。這個控制項能讓使用者在流動文件中切換頁面導向檢視 (包括一次觀看兩個頁面) 和捲動檢視。
隨著人們越來越依賴數位方式傳送資訊,螢幕上的閱讀經驗也日趨重要。WPF 透過流動文件提供靈活度高的資訊顯示方式,企圖改進 Windows 使用者在這方面的經驗。
影像
無論影像是公司商標、日落照片或是其他的內容,它都是使用者介面裡一個極為重要的部份。在 WPF 中,影像通常是以 Image 控制項顯示的。在此舉個例子,如果要顯示一個 JPEG 檔案,XAML 可能如下所示:
<Image
Width="200"
Source="C:\Documents and Settings\All Users\Documents\
My Pictures\Ava.jpg" />
這個影像的寬度設為 200,在此再提醒您一次,這裡的單位與裝置像素毫無關係。要想識別含有影像的檔案,要使用 Source 屬性。
影像檔能含有與影像相關的資訊 (中繼資料),例如關鍵字以及使用者給予的評分,而 WPF 應用程式能夠讀取和寫入這些資訊。影像還有其他更有趣的用途,例如,繪製一個旋轉中的立體物件的某一個面。這裡所介紹的簡單範例只說明常見的狀況,當然 WPF 允許將影像作為其他更廣的用途。
WPF Image 控制項能夠以各種格式顯示影像,格式包括 JPEG、BMP、TIFF、GIF 和 PNG。它還能顯示以與 Windows Vista 搭配的新 Microsoft Windows Media Photo (WMPhoto) 格式儲存的影像。無論所用的格式如何,WPF 需要靠 Windows Imaging Component (WIC) 來產生影像。除了方才列出的所有影像格式的編碼器/解碼器 (通稱為轉碼器) 之外,WIC 也能提供架構,以新增第三方轉碼器。
視訊與音訊
隨著網路和處理器的速度均大幅提升,人們日漸採用視訊方式與軟體進行互動,使用電腦播放音樂和音訊的時間也很可觀。因此,WPF 為這兩種目的提供內建支援。
這種支援全取決於 MediaElement 控制項,下面舉一個簡單的 XAML 範例,說明可如何使用這個控制項:
<MediaElement
Source="C:\Documents and Settings\All Users\Documents\
My Videos\Ruby.wmv" />
這個控制項能播放 WMV、MPEG、AVI 視訊及多種音訊格式。
平面圖形
過去 20 年來,在 Windows 中建立平面圖形的人員一直都仰賴繪圖裝置介面 (GDI) 及其新一代介面 GDI+。可是就連 Windows Form 應用程式都必須透過特殊的命名空間來存取這個功能,因為使用者介面技術本身並未整合平面繪圖。而立體繪圖的情況更棘手,因為它所需要的技術 Direct3D 是另一套截然不同的技術。有了 WPF,大部分的應用程式就可擺脫這種複雜的窘境。您可以使用 WPF 程式庫,直接以 XAML 或程序式程式碼建立平面和立體圖形。就和 WPF 其他的事情一樣,它們所用的項目只是應用程式視覺化樹狀結構的另一個部分。
WPF 將平面圖形定義成一組應用程式能用來建立影像的形狀 (Shape),它們是:
- 直線 (Line):繪製兩點之間的直線。
- 橢圓形 (Ellipse):繪製橢圓形。
- 長方形 (Rectangle):繪製長方形。
- 多邊形 (Polygon):繪製由一組連接的直線所定義出來的形狀。
- 折線 (Polyline):繪製由一組連接的直線所定義出來的折線。
- 任意圖形 (Path):繪製任意圖形,不一定要是某個形狀,可以是直線或曲線。其實,其他選項只是為了方便起見而提供的,因為任意圖形可用來繪製直線、橢圓形、長方形、多角形、折線和其他圖形。
利用這些類別來建立簡單的圖形真是易如反掌,舉例來說,下面的 XAML 能繪製出紅色的橢圓形:
<Ellipse Width="30" Height="10" Fill="Red" />
要對形狀填滿顏色需要使用筆刷 (Brush)。上面的範例使用預設值,也就是單色筆刷,不過 WPF 提供的選項很多,例如,下面範例就定義將一個長方形由紅色漸層為黃色 (垂直方向):
<Rectangle Width="30" Height="10"
Fill="HorizontalGradient Red Yellow" />
可用的筆刷不只這些,還有垂直漸層、放射漸層,以及能繪製影像和點陣圖等的筆刷。雖然我在此並沒有示範,不過形狀也可以使用畫筆 (Pen) 來指明外框的色彩、寬度和樣式。
有關 WPF 的一個重要概念是,由於所有的東西都建置在共同基礎上,整合各個方面完全不費力。應用程式可以在 Rectangle 裡面顯示 Image,在 Button 裡放置 Ellipse,還可進行其他更多的作業。正因如此,要整合平面圖形、立體圖形以及介面的其他組件十分容易。
WPF 除了有形狀之外,還提供另一組類別,以供使用平面圖形。這組類別又稱幾何 (Geometry),在很多方面都與形狀十分類似。形狀包含有 Line、Rectangle、Ellipse 和 Path 等選擇以供使用,同樣地幾何也包含有 LineGeometry、RectangleGeometry、EllipseGeometry 和 PathGeometry 可供選擇。而這兩種類別間最重要的差異在於:形狀通常是用來繪製可見的影像,幾何的主要功能是定義區域。舉例來說,如果要將某個正方形影像裁減使它符合一個圓形的大小,就可以使用 EllipseGeometry 類別來指明這個圓形的界線。同樣地,如果應用程式要定義某個測試區域,例如能偵測到滑鼠點選的區域,只要指明一個該區域的幾何即可。
最後,值得提的一點是本節所探討的所有內容,實際上都是在名為視覺層 的低階介面上實作的,要直接使用這一層建立圖形、影像和文字是可以辦到的。這麼做,有時候像是建立簡單且高效能的圖形時,大部分的應用程式會使用 WPF 提供的形狀以及其他高階抽象層。
立體圖形
平面圖形是 Windows 介面的一個共用部分,所以 WPF 在此方面提供不少技術。當前來看,立體圖形使用的情況雖然比較少,不過透過較好的資料視覺化、立體圖表、產品轉譯等等,它們能提供實質的價值。以往如果要進行立體繪圖,需要具備特殊的技能,而這通常是遊戲開發人員和其他專業群組的天下。WPF 打算藉由支援標準環境的立體圖形組件,扭轉這個局勢。
若不使用 WPF,在 Windows 上開發立體圖形通常需要依賴 Direct3D API。WPF 支援立體圖形,使之在幕後使用 Direct3D,不過開發人員所接觸到的卻是更簡單的用法。隨然在某些情況下,使用 Direct3D 比使用 WPF 還來的合理 (將於稍後說明),不過 Microsoft 的用意是希望讓 Windows 介面立體圖形的主流開發人員能夠使用 WPF。
要想在 WPF 裡顯示立體圖形,應用程式要使用到 Viewport3D 控制項,基本上,這個控制項是進入應用程式所描述的立體世界的那一個點。Viewport3D 控制項能用於 WPF 介面的任何一處,允許立體圖形出現在應出現的地方。
要想建立立體場景,開發人員需要描述一或多個模型 (Model),然後指明如何照明和檢視這些模型。和往常一樣,這些事都可使用 XAML、程式碼或混用這兩者來完成。要了要描述一個模型,WPF 提供一個 GeometryModel3D 類別,以允許定義模型的形狀,一旦定義好模型,就可套用不同種類的材質 (Material) 來控制外觀。舉例而言,SpecularMaterial 類別能使表面看起來很平滑,DiffuseMaterial 類型則相反。
無論模型使用何種材質,打光的方法多得很。DirectionalLight 提供來自某特定方向的光源,AmbientLight 則為所有場景提供一致的光源。最後,如果開發人員想要定義如何檢視模型,他們需要指明一個 照相機 (Camera)。舉例來說,PerspectiveCamera 能允許指定從哪個遠近景深和距離來檢視模型,OrthographicCamera 則可以指定從哪個距離來檢視模型:離照相機較遠的物件看起來不會比較小。
直接以 XAML 或程式碼建立複雜的立體場景並非易事。您可以假設對於絕大多數使用立體圖形的 WPF 應用程式,開發人員會使用圖形工具來產生必要的定義。雖然困難,我們還是辦到了。在標準使用者介面中使用立體圖形的能力,很可能能夠大幅改善介面螢幕的品質。
轉換與效果
WPF 除了能提供一個定義形狀與其他項目的方法,還能對它們進行旋轉、大小變更及其他作業,讓開發人員能夠轉換這些項目。在 XAML 中,就使用像是 RotateTransform 和 ScaleTransform 的項目來進行轉換,這些轉換可套用到任何一個使用者介面項目,範例如下:
</Button>
<Button Content="按此處">
<Button.RenderTransform>
<RotateTransform Angle="45" />
</Button.RenderTransform>
</Button>
RotateTransform 項目會將按鈕旋轉 45 度,隨然此類按鈕的作用不大,不過卻能證明 WPF 的設計功能廣泛。既然使用者介面的各個部分採用的基礎技術相同,您可以任意加以組合。
WPF 也有幾個預先定義的效果,它們跟轉換一樣,能運用到使用者介面的各個部分,例如 Buttons、ComboBoxes 等等。這些效果包括一個能將介面元素模糊呈現的模糊效果,一個能讓元素發出光輝的發光效果,以及一個能在介面元素後方加上陰影的陰影效果。
動畫
讓介面中的元素動起來 (把它們以動畫方式呈現),是個實用的功能。舉例來說,按一下按鈕,就能讓它能上下移動,而提供使用者更好的回應。比較複雜的動畫有助建立吸引人的介面,並可利用介面來說故事,WPF 的動畫支援就能辦到這些。
動畫和轉換一樣,能用於介面的不同部位中,包括按鈕、形狀、影像等等。實作動畫的方法是,隨著時間變更某物件的屬性值,舉例來說,Ellipse 的 Height 屬性如果每兩秒鐘就縮小一次,它看起來就像逐漸被擠壓的橢圓形。
通常而言,若您定義一組相關的動畫,對您十分有用。為了能這樣做,WPF 提供 Storyboard 類別,每個 Storyboard 都含有一個或多個時間表 (Timeline),每個時間表內具有一個或多個動畫。您會有多種時間表,讓動畫以系列方式或同步方式執行,以下是一個簡單的 (不過可能有點不完整) XAML 範例,示範如何壓縮 Ellipse:
<Ellipse Width="100" Height="50" Fill="Blue"
Name="EllipseForSquashing">
. . .
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="EllipseForSquashing"
Storyboard.TargetProperty="Height"
From="50" To="25" Duration="0:0:2" />
</Storyboard>
. . .
</Ellipse>
上述範例一開始就定義一個 Ellipse,和本文稍早提過的一樣。可是此處我還用了 Name 屬性,指派一個能讓這個 Ellipse 稍後成為參照的識別項,我雖然省略了一些細節,可是要想以 XAML 定義動畫,Storyboard 項目絕對是不可或缺的。由於 Ellipse 的 Height 屬性是 Double 型別,Storyboard 具有一個 DoubleAnimation 項目,這個項目指明將成為動畫的 Ellipse 的名稱、要變更的屬性以及變更內容為何。在本例中,Height 的值每兩秒就會從 50 變成 25。
有的動畫可能比這個範例更為艱深複雜。舉例來說,我們可以用事件來觸發滑鼠點按,讓它暫停後又再度啟動、重複幾個回合 (或一直重複) 等等。主要目標是讓開發人員能夠建立反應性更好的使用者介面,提供更多功能,並且提高介面的易用性。
資料繫結
多數的使用者介面都多都會顯示某種資料。為了讓開發人員能更輕鬆就建立出這種介面,資料繫結是一個簡單的資料顯示方法。資料繫結允許直接將某個 WPF 控制項的顯示內容與那個控制項之外的資料連接起來。舉例來說,某個 WPF TextBox 控制項裡的 Text 屬性值可以與此應用程式商務邏輯內的某個 Employee 物件內的一個 Name 屬性相互繫結。若改變其中一個屬性,另一個屬性亦有所變更。假如一位使用者更新了 TextBox 的值,Employee 物件的 Name 屬性也會所有異動,反之亦然。
這種兩個物件內的屬性連結需要用到 WPF Binding 類別,下面舉一個還算簡單的 XAML 範例加以說明:
<TextBox . . . >
<TextBox.Text>
<Binding Path="Name" />
</TextBox.Text>
</TextBox>
舉例來說,Binding 項目的 Path 屬性是用來識別 TextBox 的 Text 屬性應與哪個屬性繫結。當這個屬性所屬的物件 (將執行時期指明) 是 Common Language Runtime (CLR) 物件,且於以 C# 或 Visual Basic 語言加以定義時,就會使用 Path。WPF 的資料繫結除了能與 CLR 物件相連接之外,還可以使用 Binding 的 XPath 屬性,直接連接到 XML 資料,此選項建立一個 XPath 查詢,它會在 XML 文件裡選擇一或多個節點參照指定的資料。
如果需要更複雜的資料繫結選項,也是可以的。舉例來說,清單繫結就允許從實作標準 IEnumerable 介面的任何 CLR 物件,填入某 ListBox 控制項的內容,而需要時,還可在顯示資料前先篩選或排序資料 (雖然繫結到 ADO.NET Dataset 是可以辦到的,不過 WPF 不直支援與關聯資料庫管理系統內的資料的繫結)。無論是使用哪一個資料繫結選項,它的主要目的是盡量簡化在使用者介面中顯示資料的這個常見工作。
使用者介面自動化
WPF 介面的使用者當然就是人,不過在某些情況下,使用者介面是受到其他軟體的支配而不是人。使用 WPF 的使用者介面 (UI) 自動化,就能實作這一點。
舉例而言,假如有一位開發人員想為某個介面建立自動化測試指令碼,此時只要使用 UI 自動化所提供的程式化存取,就能建立彷彿能像人類一樣操作介面的指令碼。要想建立協助工具輔助,例如一個能大聲朗讀各項介面元素的工具,UI 自動化也十分好用。由於它允許以程式撰寫的方式逐層深入那些元素的樹狀結構,因此能夠建置此類工具。
為了能做到這一點,WPF 建立一個 UI 自動化樹狀結構,這個結構是由 AutomationElement 物件所組成的,而每個物件都代表介面上的某個東西。樹狀結構的根是 Desktop,每個開啟的應用程式都是這個根的子系,樹狀結構深入到每個這種應用程式,而每個 WPF 控制項都代表一個 (有時是數個) AutomationElement 物件。. 為了達成以程式化的方式全面存取介面,凡是使用者可能與其進行互動的東西,都以特殊的 AutomationElement 代表。舉例來說,一個具有多個按鈕的控制項就有分別代表控制項本身以及每個按鈕的特殊 AutomationElement 物件。在 UI 自動化樹狀結構裡建置這種規模層次,能讓用戶端應用程式 (無論是否為測試指令碼)、協助工具輔助或其他等東西,存取介面的每個元件,彷彿是由人在進行操作。
UI 自動化並不是 WPF 的主流部分,對多數的人而言,他們可能根本用不到。不過對於需要的人來說,像是軟體測試人員以及的行動不變的人士,他們的確 需要這個部分。畢竟,一個東西的重要性並不取決於它的使用群大小。
運用 Windows Presentation Foundation
WPF 具有多項技術,這些技術均著重於與人的互動。當今的三種相關運用方式包括:獨立 WPF 應用程式、XBAP 和 XPS 文件。在這一部分,我們就來研究一下這三個用途。
獨立 WPF 應用程式
最常見的 WPF 運用方式,就是在獨立應用程式方面。獨立的 WPF 應用程式的執行與其他 Windows 應用程式一樣,無須用到網站瀏覽器。因此,獨立應用程式是可以被完全信任的,而 WPF 的所有功能也可以被使用。完全信任也表示獨立的 WPF 應用程式能夠任意使用電腦上的其他服務,例如 Windows Communication Foundation (WCF)。
獨立的 WPF 應用程式和其他 Windows 應用程式一樣,能從本機磁碟或網路伺服器進行安裝,您還可以使用 .NET Framework 裡的設備 ClickOnce 進行安裝。ClickOnce 能讓 Internet Explorer 使用者輕鬆下載和安裝 Windows 應用程式 (包括 WPF 應用程式),它還能使這些應用程式在有更新程式時自動進行更新。
XAML 瀏覽器應用程式:XBAP
雖然獨立的 WPF 應用程式所能提供的功能最多,可是有時候它們不盡然是最佳的選擇。很多情況下,使用透過網頁瀏覽器執行的用戶端反而比使用 Windows 應用程式還來的明智。為了能讓這些用戶端擁有現代化的使用者介面,WPF 特地提供 XBAP。
下圖就是在 Internet Explorer 裡執行 XBAP。XBAP 可作為 Web 應用程式 (利用 ASP.NET、JavaServer Pages (JSP) 或它種 Web 技術所建置而成) 的用戶端。XBAP 使用 HTTP 或 SOAP 與這個 Web 應用程式進行通訊。無論所用的平台為何,您都可透過 ClickOnce 來載入 XBAP,不過在這個流程內,您不會用到任何對話方塊或提示方塊,因為 XBAP 會和網頁一樣載入。也因此,[開始] 功能表和 [新增/移除程式] 中並不會顯示 XBAP。

[圖 7] 在 Internet Explorer 中執行的 XBAP
XBAP 通常是以巡覽介面的方式呈現給使用者,不過並沒有嚴格的規定一定要如此。由於是巡覽介面,應用程式的行為就有如 Web 用戶端 (這可能與使用者所預期的一樣)。在 Internet Explorer 7 中,XBAP 會使用瀏覽器本身的 [上一頁] 和 [下一頁] 按鈕,而使用者所存取的 XAML 頁面會出現在瀏覽器的歷程記錄清單中;在 Internet Explorer 6 裡,XBAP 則是會顯示自己的 [上一頁] 和 [下一頁] 按鈕,並且會維護自己的歷程記錄清單。XBAP 能判斷所在的執行環境,並視情況作業;開發人員無須為不同的瀏覽器分別開發不同的版本。
由於 XBAP 是從網頁載入到瀏覽器中執行,因此 .NET Framework 的程式碼存取安全性只給它有限度的信任,也因為如此,有幾件事情只有獨立的 WPF 應用程式能進行,XBAP 並無法進行,舉例來說,從網際網路時區部署的 XBAP 就無法進行下列工作:
- 建立獨立的視窗。
- 顯示應用程式定義的對話方塊。
- 顯示 XBP 自己啟動的 [儲存] 對話方塊。
- 存取受限隔離儲存區之外的檔案系統。
- 作為 UI 自動化用戶端。
- 使用 WCF:WCF 應用程式具有完全信任,因此從網際網路部署的 XBAP 無法使用它。不過它們可以使用 ASP.NET Web 服務 (又稱為 ASMX) 從被載入的地方與 Web 應用程式通訊。
- 使用任何以 Windows Form、Microsoft Foundation Classes (MFC) 或直接的 Win32 呼叫所建立的使用者介面程式碼。雖然獨立的 WPF 應用程式能與這些比較舊得技術交互操作 (將於稍後說明),但它們都不許進入 XBAP 的有限信任環境。
- 使用 Unmanaged 程式碼。
前面說過,同一個程式碼基底可用於獨立的 WPF 應用程式,亦可用於以及 XBAP。若想這麼做,開發人員必須進行條件式編譯,包裝不許進入 XBAP 內部本身的功能。XBAP 版本的能力與獨立應用程式幾乎一樣,其中包括顯示文件、使用平面圖形與立體圖形、播放視訊與音訊等等,它也能利用執行它的電腦的可用繪圖硬體。
除了 XBAP 之外,若想在 Internet Explorer 裡直接顯示純 XAML 網頁也不是問題,這對於在瀏覽器中顯示靜態頁面一事相當有幫助,我們又稱它為鬆散 XAML (Loose XAML)。不過,處理事件時需要用到程式碼,也就是需要建立 XBAP。
XBAP 允許開發人員在瀏覽器應用程式內使用大部分的 WPF 功能,也允許一種共同的程式設計模型,對獨立應用程式和瀏覽器應用程式使用幾乎一模一樣的程式碼。如果 Web 應用程式的用戶端是以比較新的 Windows 平台作為目標平台,XBAP 是一個不錯的選擇。
XPS 文件
固定格式文件以 WPF 的術語來說,其實就是 XPS 文件,而它在使用者介面中顯然佔有一席之地。本文先前已經說明過 WPF 提供 DocumentViewer 控制項來顯示 XPS 文件,因此將這個控制項包含在 WPF 裡面相當合理,只不過,XPS 本身被視為 WPF 的一部分,這背後的原因就不是那麼明顯。畢竟,XPS 規格提供極為詳細的方法來定義固定格式文件,而且這些文件本身可以用於其他用途,反觀 WPF,它 的所有東西則只是以使用者介面的建立為焦點。既然如此,為何 XPS 被歸類到 WPF 裡面?
最主要的原因是 XPS 文件是以 XAML 定義的,雖然使用到的 XAML 子集相當小,包括用於版面配置的 Canvas 項目、代表文字的 Glyphs 項目以及用來建立平面圖形的 Path 項目,可是每個 XPS 文件都是的的確確的 XAML 文件,所以,將 XPS 視為 WPF 的一部分,理由十分充裕。
不過話說回來,XPS 其中一個最重要的應用程式與螢幕巡覽式使用者介面並無關係。從 Windows Vista 開始,XPS 變成了 Windows 的原生列印格式,XPS 成為一種頁面描述語言,因此 XPS 文件能直接被 XPS 感知的印表機轉譯。如此一來,從螢幕到印表機,只要使用單一描述格式 XAML 就行了。此外,它還改善了 Windows 現有的 GDI 列印機制,為複雜的圖形效果 (例如透明度和漸層) 提供較好的列印支援。
XPS 文件除了包含 XAML 之外,還能包含二進位資料 (像是各種格式的影像,其中包括 JPEG、PNG、TIFF 和 WMPhoto)、字型資料以及有關文件結構的資訊等等。需要時,您可以使用 W3C XML Signature 定義與 X.509 憑證,對 XPS 文件進行數位簽署。 無論 XPS 文件所包含的內容是什麼,每個文件都是根據 Open Packaging Conventions (OPC) 所定義的格式進行儲存作業。OPC 會指明 XML 文件 (不只是 XPS 或 XAML 文件) 裡各個部分之間的關係、如何以標準的 ZIP 格式加以儲存,以及其他等事宜。Microsoft Office 2007 也針對它的 XML 格式採用 OPC,這為兩種文件提供了共同點。
前面說過,WPF 應用程式的使用者能夠透過 WPF DocumentViewer 控制項來檢視 XPS 文件,而 Microsoft 也提供一種以 DocumentViewer 控制項為建置基礎的 XPS 檢視器應用程式,如下圖所示。這個應用程式和那個控制項一樣,能讓使用者逐頁瀏覽文件、搜尋文字或是進行其他工作。由於 XPS 文件不限定只能用於 Windows,因此 Microsoft 打算也為其他平台 (例如 Apple Macintosh) 提供 XPS 檢視器。

[圖 8] XPS 檢視器允許在讀取 XPS 文件時,一次只讀取一頁。
WPF 為了能讓開發人員使用 XPS 文件,因此提供一組 API 來建立、載入和操控 XPS 文件。WPF 應用程式也能在 OPC 層面上使用文件,允許對 XPS 文件、Office 2007 文件以及它種文件進行通用存取。使用 Microsoft Windows Workflow Foundation 建置的應用程式亦可使用這些 API 來建立會用到 XPS 文件的工作流程。
藉由允許應用程式顯示和使用固定格式文件,WPF 將現代化使用者介面裡的這個組件整合到它一貫的方式中。藉由對列印文件使用這種格式,Windows Vista 允許人們在螢幕上以及在書面裡看到一致的結果。雖然人們可能不期望使用者介面技術能提供這種文件,但是 XPS 的廣泛用途展示了 WPF 此類技術所能涵蓋的範圍。
Windows Presentation Foundation 的工具
WPF 提供開發人員許多相當實用的功能,這當然是好事一樁,但是無論功能再強大,要有好用的工具才能大幅提升這個技術的實用性。Microsoft 特別為 WPF 的開發人員和設計人員各提供一種工具,我本節中就大致介紹一下這兩種工具。
開發人員工具:Visual Studio
Visual Studio 是 Microsoft 為軟體開發人員提供的一流工具,WPF 剛上市時,Microsoft 會提供擴充的 Visual Studio 2005 功能,以讓開發人員建立 WPF 應用程式。下一版的 Visual Studio 代碼為「Orcas」,裡面將添加更多相關功能,包括 Visual Designer for WPF (有其自己的代碼:「Cider」)。開發人員若使用這個視覺化工具,將能以繪圖的方式建立 WPF 介面,然後自動產生基本的 XAML。雖然 Microsoft 目前尚未正式宣布 Orcas 的推出日期,不過暫時於 2007 年上市。
設計人員工具:Expression Interactive Designer
前面提過,WPF 的主要目的之一是要使得設計人員成為使用者介面建立的重頭人物。有了 XAML,這就不成問題了,可是前提是設計人員要有能使用的工具才行。為此,Microsoft 特別建立了 Expression Interactive Designer。
如下面的螢幕捕捉畫面所示,Expression Interactive Designer 具有傳統設計工具的某些特色,讓使用者用起來有種親切感。不過 Designer 完全把焦點放在為 WPF 應用程式建立介面 (事實上,這個工具的介面本身就是採用 WPF 建置而成)。舉例來說,請仔細看圖中右上方的 WPF 控制項清單,以及圖的底部的圖形時間表,這些都與本文前面所提到的 WPF 的功能吻合,而且這些功能現在都提供給介面設計人員使用。動畫建立可以透過繪圖方式完成,而轉換、效果與其他等作業也是一樣。此工具會產生一個 XAML 檔案,呈現設計人員的工作成果,之後這個檔案還能被匯入到 Visual Studio。

[圖 9] Expression Interactive Designer 讓設計人員建立 WPF 介面。
Microsoft 的 Expression 系列有三個產品,其中一個是 Expression Interactive Designer,另外兩個則分別為 Expression Web Designer (用來建立標準網頁介面的工具) 以及 Expression Graphic Designer (用來建立向量影像和/或點陣圖的工具)。這三者中,只有 Expression Interactive Designer 把重點放在建立 WPF 應用程式的使用者介面。設計人員可以使用其他兩種工具來建立某部分的使用者介面 (例如,使用 Expression Graphic Designer 來建立介面的 GIF 影像),不過這些工具並不是 WPF 的特定工具。此外,雖然目前發行日期尚不明確,不過 Expression 系列工具是排定在 WPF 上市之後才發行。
Windows Presentation Foundation 與其他的 Microsoft 技術
WPF 和多半的 Microsoft 新技術一樣,也會影響到 Windows 技術。在詳述前,我想先說明一點::在系統上安裝 WPF 並不會損壞任何使用 Windows Form、MFC 或其他現有技術的軟體。為 .NET Framework 3.0 的支援系統所撰寫的新應用程式會採用 WPF 來建置它們的介面,而使用舊有技術的應用程式仍繼續執行,不受到任何影響。
Windows Presentation Foundation 和 Windows Form
自從 .NET Framework 問世以來,許多應用程式就是採 Windows Form 建立而成的,現在就算有了 WPF,一些應用程式還是會繼續使用 Windows Form。舉例來說,只要執行應用程式的系統上沒有可用的 WPF,例如舊版的 Windows,這種情況下就很可能必須使用 Windows Form 來建立使用者介面。新的應用程式其實也可能因為其他因素 (例如,Windows Form 有豐富的控制項) 而採用 Windows Form,而不使用 WPF。
就算是使用 WPF 建立的應用程式,也可以因為使用某些 Windows Form 功能而受益。舉例來說,目前 Windows Form 的控制項比 WPF 豐富,以 .NET Framework 2.0 所引進的 DataGridView 控制項而言,WPF 裡面就還沒有對等的控制項,而且第三方廠商也已經建立了許多 Windows Form 供大家使用,在某些情況下,讓 WPF 應用程式使用這些現有的控制項能帶來許多好處。相反的,WPF 提供不少 Windows Form 所沒有的東西,例如立體繪圖與動畫,允許現有的 Windows Form 應用程式與 WPF 的功能整合為一,也是明智之舉。
上述兩種方法都是可行的,WPF 應用程式能夠裝載 Windows Form 控制項,而 Windows Form 應用程式也能裝載 WPF 控制項。使用者可以在同一個應用程式裡與 WPF 對話方塊及 Windows Form 對話方塊進行互動,而且一點都不會意識到兩種間的差異。
WPF 應用程式如果要裝載 Windows Form 控制項,就必須使用 WPF 的 WindowsFormsHost 控制項。這個控制項正如其名,能夠裝載 Windows Form 控制項,並且還允許它們從 WPF 應用程式裡被使用;此外,它還能裝載 ActiveX 控制項,讓 WPF 應用程式存取採用此舊有技術所建立而成的大型程式庫。同樣地,Windows Form 應用程式需要使用 ElementHost,這是一個能裝載 WPF 控制項、面板以及它種元素的 Windows Form 控制項。這兩者間,一個技術的特有工具能與針對另一個技術所撰寫的軟體搭配使用;WPF 的 Visual Designer 能夠用來放置 Windows Form 控制項,Windows Form 的設計工具能用來放置 WPF 控制項。
將 WPF 和 Windows Form 技術合併使用時有一些限制,舉例來說,將 WPF 控制項置於 Windows Form 控制項之上是不可行的,Windows Form 控制項一定要在最上層;如果將 WPF 的透明度效果與 Windows Form 控制項搭配使用,效果不彰,WPF 的轉換也一樣 。而且,因為 WindowsFormsHost 和 ElementHost 兩個控制項要求完全信任,所以使用它們的 WPF 應用程式無法執行成 XBAP。不過,大部分的 Windows 應用程式都能使用 WPF 和 Windows Form 來建立它們的介面。
Windows Presentation Foundation 和 Win32/MFC
在 2002 年的 .NET Framework 問世之前,Windows 開發人員最常用的使用者介面建置方法就是直接呼叫Win32 API 或是直接呼叫 MFC,因此為 API 提供了 C++ 包裝函式。因此,當今有許程式碼都具有這種介面,現在碰上了 WPF,我們要如何處理這些程式碼呢?
答案其實跟 Windows Form 的情況很類似,您可以在現有 Win32/MFC 程式碼內裝載 WPF 控制項,也可在 WPF 裡面裝載 Win32/MFC 控制項 (事實上,用於 WPF 與 Windows Form 之間交互操作的設備就是以 Win32/MFC 交互操作服務為基礎建置的)。WPF 提供 HwndHost 類別,允許在 WPF 裡使用 Win32/MFC 控制項,並也提供 HwndSource 類別,允許在 Win32/MFC 應用程式中使用 WPF 控制項。每個類別都會依需要來對應這兩種技術,舉例來說,HwndHost 就讓用來參照 Win32/MFC 控制項的 hWnd 看似 WPF 控制項,相反的,HwndSource 使 WPF 控制項看起來像是 hWnd。
在混用這兩種程式碼時仍有一些限制,這和 Windows Form 的情況一樣。其實,由於 Windows Form 的交互操作性是依靠 HwndHost 和 HwndSource,前一節提到的所有有關 Windows Form 控制項的限制,像是 Windows Form 控制項一定要在最上層和透明度方面的限制等,在此都適用。此外,與 Windows Form 不同的一點是,併用 WPF 和 Win32/MFC 的程式碼在 WPF Managed 程式碼環境與 Win32 的 Unmanaged 程式碼之間的交互操作方面,面臨比較大的挑戰。因此,使用 Win32/MFC 程式碼的 WPF 應用程式不可以當成 XBAP 執行。不過,正如我前面提到的,Windows 應用程式能兼用 WPF 以及 Win32/MFC,使用 WPF 並不代表必須拋棄現有應用程式的所有使用者介面程式碼。
Windows Presentation Foundation 和 Direct3D
Direct3D 是 Microsoft 的API DirectX 系列之一,它也是建立立體圖形的 Windows 開發人員的主要支柱。WPF 的問世並不代表 Direct3D 就該受到淘汰,事實上,我前面已解釋過,WPF 完全依賴 Direct3D 進行轉譯工作。不過,因為 WPF 也提供開發人員建立立體圖形的功能,開發人員在繪製立體圖形時必須二選一。
然後,這個抉擇並不困難,Direct3D 仍是開發高難度立體圖案的最佳選擇,像是遊戲和以立體圖形為主的技術應用程式 (例如高端的精密視覺化應用程式),而 WPF 的第一個發行版本並非針對此類軟體而設計。
不過,WPF 的確將立體圖形繪製推廣至不具有專精技能的使用者。它還允許利用 XBAP 來使用 Web 的立體圖形,將它們與平面圖形、文件及應用程式使用者介面的其他組件等緊密整合。此外,WPF 應用程式也能透過前面所說的 HwndHost 類別來裝載 Direct3D 程式碼。WPF 和 Direct3D 兩者各扮演自己獨特的角色,而兩者日後在 Windows 平台方面均有待發展。
Windows Presentation Foundation 和 AJAX/"Atlas"
開發人員能使用 AJAX 來建立反應更快速的瀏覽器用戶端。AJAX 允許使用者與應用程式進行互動,且針對每個要求完全無須重整頁面 (因此也不用與 Web 伺服器來回傳遞)。方法是,AJAX 依賴瀏覽器對 XMLHttpRequest 物件的支援;這個概念首度出現於 1990 年代末期的 Internet Explorer 5.0。今日,很多瀏覽器都支援 XMLHttpRequest,而 AJAX 現象因此應運而生。
可是,建立 AJAX 用戶端並非易事,為了協助建立流程,Microsoft 建立了一套技術,代碼為「Atlas」。Atlas 是建立 AJAX 應用程式時所需的一組程式庫、控制項和其他等項目,裡面有用戶端程式碼程式庫,能在不同的瀏覽器裡 (不僅是 Internet Explorer) 和 ASP.NET 的伺服器端擴充功能內作業。它的主要目標是簡化具有 AJAX 用戶端的 Web 應用程式的建置工作。
由於 AJAX 受到許多瀏覽器的支援,因此深深吸引著開發人員,不過,即使 AJAX 有助為 Web 使用者建立出互動性更強的介面,它在所支援的內容類型方面並無改善。AJAX 無法獨立支援圖形、視訊、動畫以及其他等現代化的介面樣式,對於支援 WPF 的用戶端來說,如果應用程式需要這些支援,則開發人員可能會以 XBAP 來撰寫。
Windows Presentation Foundation 和 "WPF/E"
Web 應用程式若使用 XBAP,就能提供使用者絕大部分的 WPF 功能,但是 XBAP 要求要在用戶端電腦上安裝 WPF,而這對它的適用性大打折扣,像是那些必須呈現現代化介面而且必須從 Macintosh 或其他不支援 WPF 的系統上存取的 Web 應用程式,它們要怎麼辦呢?
為了因應此問題,日後即將會推出一個代碼為「WPF/E」的技術。WPF/E 裡的 E 代表的是 Everywhere (任何地方),它能在多種用戶端平台上提供一個WPF 功能子集,這些平台包括 Macintosh、小型裝置等平台,而網頁瀏覽器則包括 Internet Explorer、Firefox 和 Netscape。這個子集包括平面圖形、影像、視訊、動畫和文字等。不過,WPF/E 裡面省略了一些 XBAP 的功能,像是對立體圖形、文件和硬體加速等功能。
開發人員可以利用 JavaScript 來建立 WPF/E 應用程式。WPF/E 還會包含 .NET Framework 的跨平台子集,允許利用 C# 和 Visual Basic 進行開發工作。WPF/E 並非 .NET Framework 3.0 的一部分,因此會等到 2007 年時才發行,屆時 Web 應用程式的建立者在用戶端的建置方面就多了一項選擇。此一選擇讓他們能使用更多種平台,並且擁有更廣的平台功能。
結論
在許多應用程式裡面,最重要的部分莫非於使用者介面。盡可能地提升介面效率,能為依賴它的使用者和組織帶來龐大的利益。而 WPF 的主要目標就是協助開發人員提供這些利益,因此,對建立或使用 Windows 應用程式的人士而言,WPF 是一大福音。
WPF 能為現代化使用者介面提供統一的平台,有助設計人員積極參與這些介面的建立,並允許為獨立應用程式與瀏覽器應用程式使用共同的程式撰寫模型,它的目標在於大幅改善 Windows 的使用經驗。一些它將取代的技術,在過去 20 多年來一直是 Windows 使用者介面的基礎。而 WPF 的目的是要替未來 20 年奠定良好的根基。
作者簡介
David Chappell 任職於加州舊金山的 Principal of Chappell & Associates (www.davidchappell.com (英文))。筆者從事演說、寫作和諮詢服務等工作,藉此協助世界各地的技術專業人員瞭解和使用企業軟體,並且協助他們做出與企業軟體相關的最佳決策。