WPF是一個新的客戶端用戶界面技術,是.NET 3.0 框架的一部分。軟件設計者一直面臨著為他們的應用程序選擇一個正確的表示層技術。如果你一直在開發Windows平臺下的應用程序,它的范圍是狹窄的。要么你可以創建一個網絡應用程序,一個智能的客戶機程序,一個移動設備,或者是一些取決于目標對象的結合程序。你所選擇的分別在.NET space - ASP.NET, Windows Forms和 Compact 框架里給你提供一個相當短的實用選項表。
現在一種新的選擇即將來臨,你也要考慮這種新選擇。WPF主要適合智能客戶空間,但是網絡空間里也有覆迭區。目前WPF沒有應用于移動設備里,但是WPF Everywhere(即將面世的派生技術)在不久的將來會給設備帶來某些新的性能。本文簡單地討論了WPF的關鍵概念。告訴你它是怎樣適合你的表示層框架,以及怎樣改變現在你開發客戶應用程序的方式。本文也討論了WPF與Windows Forms的互操作性,還將展現給大家一個例子:使用互操作性來逐步轉移到WPF,而不必大規模的改動。
WPF概述
當你接觸WPF時,你第一個可能想到的問題就是我們為什么需要一個新的表示技術。我們給智能客戶端提供了Windows Forms,為網絡提供了ASP.NET。為什么不提高這些技術來增加新的性能呢?使用現有的技術來建立新功能的問題就在于經常把某些東西提高到一個新的水平,而你需要一個全新的基礎來建立這些性能。你不能在只為兩層樓而設計的板子上蓋一座摩天大樓。你必須將它拆除,重新再建。當談到設計表面層的解決辦法時,網絡在某些方面是很擅長,Windows Forms在其他方面很強。但是作為設計師和開發者,我們希望得到兩者的優點。這就是WPF提供給我們的。
WPF通過引進表示層技術打破了傳統的Windows桌面應用程序,表示層技術主要集中在最佳化客戶的感官體驗,主要是視覺體驗。網絡已經進步相當大,使用圖像、格式、文本,甚至音頻及視頻的結合體,在瀏覽器中比在Windows應用程序中更容易顯示豐富的,視覺上更引人注目的內容。但是,由于網絡分離的請求-應答模式,在網絡上提供豐富的交互式體驗比在Windows應用程序上更難。隨著AJAX技術的引進,情況將會轉好。但是,事實是如果你想最佳化用戶的交互式體驗,你需要一個可以利用桌面操作系統全部性能的應用程序。通過平衡客戶機器性能,WPF在Windows應用程序里及通過網絡更容易表現豐富的交互式圖形。圖1表示了由InterKnowlogy 開發的示例程序,此應用程序允許三維模式的交互式操作(選擇與旋轉)。
圖1 :InterKnowlogy 三維合作
構建WPF應用程序其中一個核心概念就是用來構建應用程序的一切事物都只是一個元素。控件,形狀,3維模式,圖像,聲音,視頻,格式都只是元素。WPF可以讓你很容易展現的元素包括:
• 貫穿應用程序元素的均一地使用的格式化內容(顏色,字體,圖像,形狀)
• 2維和3維形狀,圖像及模式
• 傳統用戶界面控件
• 任何元素的動畫
WPF的另一個關鍵特點就是:在開發windows應用程序時,增加了抽象性水平。首先在應用程序的用戶界面控件、圖形對象、格式及其他對象中有線模糊,所以能當做元素處理。你可以從單個元素或元素集中定義資源,通過應用程序使用這些元素。你可以對經過應用程序卻沒有在綁定控件間直接耦合的數據源或者是正在運行的數據進行定義。你甚至可以定義控件模板,從控件模板最初是怎樣設計來渲染它本身出發,代替一個控件的表達渲染。
WPF 也允許你使用新的XAML來用標記定義應用程序的靜態結構。這個方法與ASP.NET使用標記從應用程序的動態行為中分離布局的方法相似。使用WPF,你可以表達XAML里所有的,部分的或者非XAML的邏輯。就像ASP.NET,XAML允許你在標記文件里包含腳本模塊化一樣,此標記文件中包括C#或者 VB代碼,因此你能在XAML文件里編寫整個應用程序。然而,在Visual Studio中使用XAML的默認方式就是使用XAML定義你的用戶界面元素的結構,然后在單個C# 或者 Visual Basic代碼后置的檔案中使用程序設計代碼來連接動態部分。然而,你可以不那樣做,你可以用純代碼或純XAML來編寫整個應用程序,這在于此應用程序是用來干什么的,以及你想怎樣管理這些代碼。
采用WPF
WPF與.NET 3.0 Framework一起運轉,支持Windows XP SP2, Windows Server 2003和Windows Vista。采用WPF時有一個關鍵因素。如果你不能在你的用戶機器上安裝.NET 3.0 Framework,你就不能使用WPF為客戶應用程序服務。
如果你馬上使用WPF,另一個要考慮的關鍵因素與開發表示層技術的能力有關。盡管運轉時間WPF 庫是the .NET Framework 3.0的一部分,將在06年11月發行,但是WPF的設計時間工具在Visual Studio的下一個版本(叫做Orcas)發行時才會發行。現在有Orcas設計器的CTP版本可用于WPF,但是與Windows Forms 或是 ASP.NET 設計器比起來,CTP版本相當不成熟。現在也有Expressions Interactive Designer測試版(一種的新開發WPF應用程序的設計工具),但是在被承認是可用的產品代碼之前,還有很長的路要走。它面向專業設計師而不是軟件開發者,因此你將會體驗到和在Visual Studio里不同的東西。
由于WPF設計工具系列的現狀,你必須仔細考慮是否在.NET 3.0發行時你就馬上采用WPF還是等到設計工具更成熟時再用。如果你試圖開發標準的商業應用程序(有很多傳統控件例如按鈕,文本框,組合框,數據網格),然后在使用WPF開發這些應用程序時,生產力可能不大。生產力的降低一部分是由于采用新技術要走一些彎路,但就算不會那么艱難,也會因為設計時間工具的不成熟導致你的發展計劃受阻。你不得不使用XAML, C#或 VB代碼,而不是使用設計器的拖放操作控件,來開發大部分的用戶界面。在這一點上,WPF設計器中有一些控件拖放定義的性能,隨著時間的推進,這些性能終究會成熟。但是現在對于定義你的windows版面布局及組合控件特性和數據綁定上,WPF設計器和 the Windows Forms 設計器之間在性能方面仍有很大的差距。現有可用的控件裝置有一些缺點,由于明顯缺乏數據綁定網格控件,使得在WPF中普通商業應用軟件的使用情況比在Windows Forms中更困難。
另一方面,如果你想采用WPF來利用WPF中豐富的圖形處理能力,例如3d模式,動畫,豐富的應用程序風格,使用WPF要比使用Windows Forms更快更清楚地完成這些任務。它真正取決于你想完成什么任務。代碼按鈕,文本框,窗體的交替使用可能會把你的應用程序的外觀和圖形性能發展到一個更高的水平。可視的引人注目的應用程序可以區別對待表面層技術的成功與失敗,尤其當目標對象是消費者時。
減輕主流商業應用程序生產力潛在損失的一個辦法就是使用Windows Forms 和 WPF結合體。在本文后面討論的兩種技術有很好的互用性性能。當每一種技術都充分使用時,你可以在單個應用程序中利用互用性來使用Windows Forms 和WPF。你也可以使用這種性能逐步將現有的應用程序轉移到WPF中。
WPF應用程序形式
這里有兩種WPF應用程序可供選擇,傳統windows桌面應用程序和XAML 瀏覽器應用程序。WPF windows應用程序以自己的過程在用戶桌面上運轉,可以利用客戶機器上的.NET Framework, WPF,和其他資源的全部性能。XAML瀏覽器應用程序是在瀏覽器中運行的WPF應用程序。
XAML瀏覽器應用程序是在瀏覽器中運行的WPF應用程序這一概念容易讓人誤解。WPF不是其他網絡技術的替代品。網絡瀏覽器客戶技術最顯著的特點就是它們能在多個瀏覽器和多個平臺上運行。換句話說,你的用戶可以運行在比在Windows桌面應用程序更廣泛的配置上。一個XAML 瀏覽器應用程序和大型配套桌面WPF應用程序有相同的限制,即客戶機器必須安裝有.NET 3.0 Framework。那意味著客戶機必須是Windows XP SP2或者更新版的。那是一個更有限制性的設置,而不僅僅說他們需要一個兼容的瀏覽器。
要注意到XAML瀏覽器應用程序還有另外一個限制。他們只允許從代碼訪問安全區域運行的安全許可(基于你在瀏覽器內訪問的地址)。這意味著每一個XAML瀏覽器應用程序將在局域網或互聯網上運行,這有嚴格的限制許可。結果,使用XAML瀏覽器應用程序,除了顯示豐富的圖形或使網頁呼叫回到原始站點,你不能做更多的事情。你的XAML 瀏覽器應用程序不能訪問客戶文件系統和數據庫,除了回到它出發的原始網站外你不能使網頁回到其他站點。
你可能會想既然有這么多缺陷,為什么還要使用XAML瀏覽器應用程序。我認為主要原因是如果用戶通過現有的網站或入口實現你要的功能,就要展現一個一致的用戶體驗。通過使用WPF,你提供的體驗比用其他網絡技術提供的體驗要更豐富,聯系得更緊密。但是對于用戶來說,他們好像進入到站點的另一頁,而事實卻是“那一頁”正在使用WPF。如果在機器上安裝了.NET 3.0這將是很顯然的。
WPF/e
WPF/e是一種派生技術,它將擴大WPF的使用范圍,允許你在WPF的基礎上建立應用程序。這些應用程序既能在瀏覽器內運行,也可以被更廣范圍的客戶(包括其他平臺)運行。WPF/e不會在.NET 3.0內和WPF一起發行,但不久后將面世,很可能在2007年。 WPF/e在瀏覽器內使用一個ActiveX控件或其他形式的自動安裝的宿主組件。此組件在沒有依賴宿主瀏覽器的物體模塊或特殊的腳本性能情況下,也能在瀏覽器內運行WPF內容和控件。一個簡單的比喻就是把WPF/e看成和在瀏覽器內運行的和Macromedia Flash或Apple QuickTime相似的技術,其呈現的內容比瀏覽器本身呈現得更豐富。就WPF/e來說,將被提交的內容將是WPF應用程序。WPF/e支持的功能是WPF API全部性能的子集,而且也不是最終決定下來的。但是我期望這些性能與我前面談到得XAML瀏覽器應用程序的性能相似——你可以處理豐富的圖形,音頻,還可以呼叫回到原始網址(可能在宿主網頁內使用AJAX技術),但是與訪問其他資源無關。然而,擁有一個好的從宿主站點顯示服務的分布式結構能讓你使用WPF/e實現許多功能。請關注更多即將發布的與WPF/e有關的信息。
開發WPF應用程序
根據應用程序要做的任務來開發WPF的應用程序,可以選擇純代碼方法,XAML代碼方法或者兩者的結合方法。后者將是最通用的,因為采用這樣方法,你可以從這個設計工具中得到最大的利益,可維護性,靈活性,而且使你的代碼更有表達力。基本上,你在WPF中所作的一切僅僅是針對WPF .NET類庫中類型的代碼,因而代碼整個范圍的功能性對你是可用的。使用XAML操作接口讓你把可以更公開表達的對象設置在一種形式中,這種形式更方便于設計工具和設計者操作和定義。
一個WPF應用程序由一個層次的元素構成。最高等級的基本編程模式和Windows Forms并非很不相同。你創建一個應用程序類別的實例,從Windows類別(或一個派生類別)創建一個最高等級的窗口,并運行這個程序。和VB Windows Forms應用程序一樣,如果你沒有明確地創建一個你自己的進入點,這個進入點(主方法)將自動產生。
例如,在下面圖2中的兩個XAML文件公開創建了一個應用程序類實例和一個窗口類實例。這個窗口有它的第一個子要素作為網格。在WPF中,這個網格控件就像一個HTML表格或使Windows Forms2.0中的表格設計面板。它僅能提供給你一個矩形網格容器,你能夠把其他元素放置在里面用于設計。在網格之內,XAML定義了兩行兩列,然后使用附加屬性放置兩個文字塊控件和兩個文本框控件在這個網格單元中。
// App.xaml
<Application x:Class="SimpleWPFApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml"/>
// Window1.xaml
<Window x:Class="SimpleWPFApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title=" SimpleWPFApp" Height="100" Width="270">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0">Name:</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0">Phone:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Width="150"/>
<TextBox Grid.Row="1" Grid.Column="1" Width="150"/>
</Grid>
</Window>
產生的應用程序如圖2所示。這個窗口顯示了Windows Vista邊框和標題欄風格,那是我一直用的。
如果在Windows XP和Server 2003上運行,將會有這些操作系統的標準標題欄和邊框風格。
圖3運行XAML應用程序
同樣的應用程序能用純代碼的方式來表示。
class Program
{
[STAThread]
static void Main()
{
Application app = new Application();
Window win = new Window();
win.Width = 270;
win.Height = 100;
win.Title = "SimpleWPFAppCodeOnly";
Grid grid = new Grid();
win.Content = grid;
RowDefinition row1 = new RowDefinition();
row1.Height = new GridLength(0, GridUnitType.Auto);
RowDefinition row2 = new RowDefinition();
row2.Height = new GridLength(0, GridUnitType.Auto);
grid.RowDefinitions.Add(row1);
grid.RowDefinitions.Add(row2);
ColumnDefinition col1 = new ColumnDefinition();
col1.Width = new GridLength(0, GridUnitType.Auto);
ColumnDefinition col2 = new ColumnDefinition();
col2.Width = new GridLength(0, GridUnitType.Auto);
grid.ColumnDefinitions.Add(col1);
grid.ColumnDefinitions.Add(col2);
TextBlock label1 = new TextBlock();
label1.Text = "Name:";
grid.Children.Add(label1);
TextBlock label2 = new TextBlock();
label2.Text = "Phone";
grid.Children.Add(label2);
TextBox tb1 = new TextBox();
tb1.Width = 150;
grid.Children.Add(tb1);
TextBox tb2 = new TextBox();
tb2.Width = 150;
grid.Children.Add(tb2);
Grid.SetColumn(label1, 0);
Grid.SetColumn(label2, 0);
Grid.SetRow(label1, 0);
Grid.SetRow(label2, 1);
Grid.SetColumn(tb1, 1);
Grid.SetColumn(tb2, 1);
Grid.SetRow(tb1, 0);
Grid.SetRow(tb2, 1);
app.Run(win);
}
}
正如你在純代碼版本中所看到的,盡管XML比代碼更冗長,在許多WPF元素的情況下,XAML實際上更加緊湊。因為通過XML內聯屬性很多屬性能夠單獨的被設置而不需要單獨的一行代碼來設置。同樣的,你不必加入一個元素作為另一個元素的子元素,因為在可擴展應用程序標記語言XAML標簽的嵌套里,那種關系是隱式的。
你也可以從代碼看到由XAML產生的成分并非完全不同于你在Windows Forms或者ASP.NET中所做的。這個窗口是最高層元素,增加網格作為子元素,加文本塊和文本框控件作為網格的子元素等等。
當你開始連接事件處理器控制事件時,你經常會通過C#或VB代碼來實現。XAML代碼編譯成一個部分類,你可以通過另一個部分類文件加任何代碼到這個部分類中。在這一點上,Visual Studio遵循一種同樣的ASP.NET方法,它為操作接口創建一個Window1.XAML文件,并在部分類中為代碼隱藏創建一個Window1.XAML.cs文件。
另一件你可能嘗試理解的事情是XAML屬性或者代碼行,在那里,你明確指明包含的控件在哪一行、哪一列。這樣做用到了WPF中的一個新的概念,附加屬性。在XAML中,看上去有稱為Grid.Row和Grid.Column的屬性,Grid.Row和Grid.Column定義在控件類上。為每一個他們能用到的可能的文本中的控件明確地定義屬性,會導致對象模型混亂。但是,單獨的代碼版本讓我們更清楚實際上什么正在運行。附加屬性要求網格上的動態方法建立一個與被包含的控件相聯系的網格級的屬性。如果你接觸過Windows Forms擴展提供控件,其概念和這里的是相似的。
建立更復雜的WPF應用程序遵循你在這里所看到的相類似的模式。定義層次結構上的更多元素,此層次結構包括你的應用程序的窗口。這些元素可能是容器控件的任何組合,例如網格,個別控件比如文本框,式樣,幾何,動畫時間標尺和情節串連圖板,3維模型,視頻等等。