WPF是一個(gè)新的客戶端用戶界面技術(shù),是.NET 3.0 框架的一部分。軟件設(shè)計(jì)者一直面臨著為他們的應(yīng)用程序選擇一個(gè)正確的表示層技術(shù)。如果你一直在開發(fā)Windows平臺(tái)下的應(yīng)用程序,它的范圍是狹窄的。要么你可以創(chuàng)建一個(gè)網(wǎng)絡(luò)應(yīng)用程序,一個(gè)智能的客戶機(jī)程序,一個(gè)移動(dòng)設(shè)備,或者是一些取決于目標(biāo)對象的結(jié)合程序。你所選擇的分別在.NET space - ASP.NET, Windows Forms和 Compact 框架里給你提供一個(gè)相當(dāng)短的實(shí)用選項(xiàng)表。
現(xiàn)在一種新的選擇即將來臨,你也要考慮這種新選擇。WPF主要適合智能客戶空間,但是網(wǎng)絡(luò)空間里也有覆迭區(qū)。目前WPF沒有應(yīng)用于移動(dòng)設(shè)備里,但是WPF Everywhere(即將面世的派生技術(shù))在不久的將來會(huì)給設(shè)備帶來某些新的性能。本文簡單地討論了WPF的關(guān)鍵概念。告訴你它是怎樣適合你的表示層框架,以及怎樣改變現(xiàn)在你開發(fā)客戶應(yīng)用程序的方式。本文也討論了WPF與Windows Forms的互操作性,還將展現(xiàn)給大家一個(gè)例子:使用互操作性來逐步轉(zhuǎn)移到WPF,而不必大規(guī)模的改動(dòng)。
WPF概述
當(dāng)你接觸WPF時(shí),你第一個(gè)可能想到的問題就是我們?yōu)槭裁葱枰粋€(gè)新的表示技術(shù)。我們給智能客戶端提供了Windows Forms,為網(wǎng)絡(luò)提供了ASP.NET。為什么不提高這些技術(shù)來增加新的性能呢?使用現(xiàn)有的技術(shù)來建立新功能的問題就在于經(jīng)常把某些東西提高到一個(gè)新的水平,而你需要一個(gè)全新的基礎(chǔ)來建立這些性能。你不能在只為兩層樓而設(shè)計(jì)的板子上蓋一座摩天大樓。你必須將它拆除,重新再建。當(dāng)談到設(shè)計(jì)表面層的解決辦法時(shí),網(wǎng)絡(luò)在某些方面是很擅長,Windows Forms在其他方面很強(qiáng)。但是作為設(shè)計(jì)師和開發(fā)者,我們希望得到兩者的優(yōu)點(diǎn)。這就是WPF提供給我們的。
WPF通過引進(jìn)表示層技術(shù)打破了傳統(tǒng)的Windows桌面應(yīng)用程序,表示層技術(shù)主要集中在最佳化客戶的感官體驗(yàn),主要是視覺體驗(yàn)。網(wǎng)絡(luò)已經(jīng)進(jìn)步相當(dāng)大,使用圖像、格式、文本,甚至音頻及視頻的結(jié)合體,在瀏覽器中比在Windows應(yīng)用程序中更容易顯示豐富的,視覺上更引人注目的內(nèi)容。但是,由于網(wǎng)絡(luò)分離的請求-應(yīng)答模式,在網(wǎng)絡(luò)上提供豐富的交互式體驗(yàn)比在Windows應(yīng)用程序上更難。隨著AJAX技術(shù)的引進(jìn),情況將會(huì)轉(zhuǎn)好。但是,事實(shí)是如果你想最佳化用戶的交互式體驗(yàn),你需要一個(gè)可以利用桌面操作系統(tǒng)全部性能的應(yīng)用程序。通過平衡客戶機(jī)器性能,WPF在Windows應(yīng)用程序里及通過網(wǎng)絡(luò)更容易表現(xiàn)豐富的交互式圖形。圖1表示了由InterKnowlogy 開發(fā)的示例程序,此應(yīng)用程序允許三維模式的交互式操作(選擇與旋轉(zhuǎn))。
圖1 :InterKnowlogy 三維合作
構(gòu)建WPF應(yīng)用程序其中一個(gè)核心概念就是用來構(gòu)建應(yīng)用程序的一切事物都只是一個(gè)元素。控件,形狀,3維模式,圖像,聲音,視頻,格式都只是元素。WPF可以讓你很容易展現(xiàn)的元素包括:
• 貫穿應(yīng)用程序元素的均一地使用的格式化內(nèi)容(顏色,字體,圖像,形狀)
• 2維和3維形狀,圖像及模式
• 傳統(tǒng)用戶界面控件
• 任何元素的動(dòng)畫
WPF的另一個(gè)關(guān)鍵特點(diǎn)就是:在開發(fā)windows應(yīng)用程序時(shí),增加了抽象性水平。首先在應(yīng)用程序的用戶界面控件、圖形對象、格式及其他對象中有線模糊,所以能當(dāng)做元素處理。你可以從單個(gè)元素或元素集中定義資源,通過應(yīng)用程序使用這些元素。你可以對經(jīng)過應(yīng)用程序卻沒有在綁定控件間直接耦合的數(shù)據(jù)源或者是正在運(yùn)行的數(shù)據(jù)進(jìn)行定義。你甚至可以定義控件模板,從控件模板最初是怎樣設(shè)計(jì)來渲染它本身出發(fā),代替一個(gè)控件的表達(dá)渲染。
WPF 也允許你使用新的XAML來用標(biāo)記定義應(yīng)用程序的靜態(tài)結(jié)構(gòu)。這個(gè)方法與ASP.NET使用標(biāo)記從應(yīng)用程序的動(dòng)態(tài)行為中分離布局的方法相似。使用WPF,你可以表達(dá)XAML里所有的,部分的或者非XAML的邏輯。就像ASP.NET,XAML允許你在標(biāo)記文件里包含腳本模塊化一樣,此標(biāo)記文件中包括C#或者 VB代碼,因此你能在XAML文件里編寫整個(gè)應(yīng)用程序。然而,在Visual Studio中使用XAML的默認(rèn)方式就是使用XAML定義你的用戶界面元素的結(jié)構(gòu),然后在單個(gè)C# 或者 Visual Basic代碼后置的檔案中使用程序設(shè)計(jì)代碼來連接動(dòng)態(tài)部分。然而,你可以不那樣做,你可以用純代碼或純XAML來編寫整個(gè)應(yīng)用程序,這在于此應(yīng)用程序是用來干什么的,以及你想怎樣管理這些代碼。
采用WPF
WPF與.NET 3.0 Framework一起運(yùn)轉(zhuǎn),支持Windows XP SP2, Windows Server 2003和Windows Vista。采用WPF時(shí)有一個(gè)關(guān)鍵因素。如果你不能在你的用戶機(jī)器上安裝.NET 3.0 Framework,你就不能使用WPF為客戶應(yīng)用程序服務(wù)。
如果你馬上使用WPF,另一個(gè)要考慮的關(guān)鍵因素與開發(fā)表示層技術(shù)的能力有關(guān)。盡管運(yùn)轉(zhuǎn)時(shí)間WPF 庫是the .NET Framework 3.0的一部分,將在06年11月發(fā)行,但是WPF的設(shè)計(jì)時(shí)間工具在Visual Studio的下一個(gè)版本(叫做Orcas)發(fā)行時(shí)才會(huì)發(fā)行?,F(xiàn)在有Orcas設(shè)計(jì)器的CTP版本可用于WPF,但是與Windows Forms 或是 ASP.NET 設(shè)計(jì)器比起來,CTP版本相當(dāng)不成熟。現(xiàn)在也有Expressions Interactive Designer測試版(一種的新開發(fā)WPF應(yīng)用程序的設(shè)計(jì)工具),但是在被承認(rèn)是可用的產(chǎn)品代碼之前,還有很長的路要走。它面向?qū)I(yè)設(shè)計(jì)師而不是軟件開發(fā)者,因此你將會(huì)體驗(yàn)到和在Visual Studio里不同的東西。
由于WPF設(shè)計(jì)工具系列的現(xiàn)狀,你必須仔細(xì)考慮是否在.NET 3.0發(fā)行時(shí)你就馬上采用WPF還是等到設(shè)計(jì)工具更成熟時(shí)再用。如果你試圖開發(fā)標(biāo)準(zhǔn)的商業(yè)應(yīng)用程序(有很多傳統(tǒng)控件例如按鈕,文本框,組合框,數(shù)據(jù)網(wǎng)格),然后在使用WPF開發(fā)這些應(yīng)用程序時(shí),生產(chǎn)力可能不大。生產(chǎn)力的降低一部分是由于采用新技術(shù)要走一些彎路,但就算不會(huì)那么艱難,也會(huì)因?yàn)樵O(shè)計(jì)時(shí)間工具的不成熟導(dǎo)致你的發(fā)展計(jì)劃受阻。你不得不使用XAML, C#或 VB代碼,而不是使用設(shè)計(jì)器的拖放操作控件,來開發(fā)大部分的用戶界面。在這一點(diǎn)上,WPF設(shè)計(jì)器中有一些控件拖放定義的性能,隨著時(shí)間的推進(jìn),這些性能終究會(huì)成熟。但是現(xiàn)在對于定義你的windows版面布局及組合控件特性和數(shù)據(jù)綁定上,WPF設(shè)計(jì)器和 the Windows Forms 設(shè)計(jì)器之間在性能方面仍有很大的差距?,F(xiàn)有可用的控件裝置有一些缺點(diǎn),由于明顯缺乏數(shù)據(jù)綁定網(wǎng)格控件,使得在WPF中普通商業(yè)應(yīng)用軟件的使用情況比在Windows Forms中更困難。
另一方面,如果你想采用WPF來利用WPF中豐富的圖形處理能力,例如3d模式,動(dòng)畫,豐富的應(yīng)用程序風(fēng)格,使用WPF要比使用Windows Forms更快更清楚地完成這些任務(wù)。它真正取決于你想完成什么任務(wù)。代碼按鈕,文本框,窗體的交替使用可能會(huì)把你的應(yīng)用程序的外觀和圖形性能發(fā)展到一個(gè)更高的水平??梢暤囊俗⒛康膽?yīng)用程序可以區(qū)別對待表面層技術(shù)的成功與失敗,尤其當(dāng)目標(biāo)對象是消費(fèi)者時(shí)。
減輕主流商業(yè)應(yīng)用程序生產(chǎn)力潛在損失的一個(gè)辦法就是使用Windows Forms 和 WPF結(jié)合體。在本文后面討論的兩種技術(shù)有很好的互用性性能。當(dāng)每一種技術(shù)都充分使用時(shí),你可以在單個(gè)應(yīng)用程序中利用互用性來使用Windows Forms 和WPF。你也可以使用這種性能逐步將現(xiàn)有的應(yīng)用程序轉(zhuǎn)移到WPF中。
WPF應(yīng)用程序形式
這里有兩種WPF應(yīng)用程序可供選擇,傳統(tǒng)windows桌面應(yīng)用程序和XAML 瀏覽器應(yīng)用程序。WPF windows應(yīng)用程序以自己的過程在用戶桌面上運(yùn)轉(zhuǎn),可以利用客戶機(jī)器上的.NET Framework, WPF,和其他資源的全部性能。XAML瀏覽器應(yīng)用程序是在瀏覽器中運(yùn)行的WPF應(yīng)用程序。
XAML瀏覽器應(yīng)用程序是在瀏覽器中運(yùn)行的WPF應(yīng)用程序這一概念容易讓人誤解。WPF不是其他網(wǎng)絡(luò)技術(shù)的替代品。網(wǎng)絡(luò)瀏覽器客戶技術(shù)最顯著的特點(diǎn)就是它們能在多個(gè)瀏覽器和多個(gè)平臺(tái)上運(yùn)行。換句話說,你的用戶可以運(yùn)行在比在Windows桌面應(yīng)用程序更廣泛的配置上。一個(gè)XAML 瀏覽器應(yīng)用程序和大型配套桌面WPF應(yīng)用程序有相同的限制,即客戶機(jī)器必須安裝有.NET 3.0 Framework。那意味著客戶機(jī)必須是Windows XP SP2或者更新版的。那是一個(gè)更有限制性的設(shè)置,而不僅僅說他們需要一個(gè)兼容的瀏覽器。
要注意到XAML瀏覽器應(yīng)用程序還有另外一個(gè)限制。他們只允許從代碼訪問安全區(qū)域運(yùn)行的安全許可(基于你在瀏覽器內(nèi)訪問的地址)。這意味著每一個(gè)XAML瀏覽器應(yīng)用程序?qū)⒃诰钟蚓W(wǎng)或互聯(lián)網(wǎng)上運(yùn)行,這有嚴(yán)格的限制許可。結(jié)果,使用XAML瀏覽器應(yīng)用程序,除了顯示豐富的圖形或使網(wǎng)頁呼叫回到原始站點(diǎn),你不能做更多的事情。你的XAML 瀏覽器應(yīng)用程序不能訪問客戶文件系統(tǒng)和數(shù)據(jù)庫,除了回到它出發(fā)的原始網(wǎng)站外你不能使網(wǎng)頁回到其他站點(diǎn)。
你可能會(huì)想既然有這么多缺陷,為什么還要使用XAML瀏覽器應(yīng)用程序。我認(rèn)為主要原因是如果用戶通過現(xiàn)有的網(wǎng)站或入口實(shí)現(xiàn)你要的功能,就要展現(xiàn)一個(gè)一致的用戶體驗(yàn)。通過使用WPF,你提供的體驗(yàn)比用其他網(wǎng)絡(luò)技術(shù)提供的體驗(yàn)要更豐富,聯(lián)系得更緊密。但是對于用戶來說,他們好像進(jìn)入到站點(diǎn)的另一頁,而事實(shí)卻是“那一頁”正在使用WPF。如果在機(jī)器上安裝了.NET 3.0這將是很顯然的。
WPF/e
WPF/e是一種派生技術(shù),它將擴(kuò)大WPF的使用范圍,允許你在WPF的基礎(chǔ)上建立應(yīng)用程序。這些應(yīng)用程序既能在瀏覽器內(nèi)運(yùn)行,也可以被更廣范圍的客戶(包括其他平臺(tái))運(yùn)行。WPF/e不會(huì)在.NET 3.0內(nèi)和WPF一起發(fā)行,但不久后將面世,很可能在2007年。 WPF/e在瀏覽器內(nèi)使用一個(gè)ActiveX控件或其他形式的自動(dòng)安裝的宿主組件。此組件在沒有依賴宿主瀏覽器的物體模塊或特殊的腳本性能情況下,也能在瀏覽器內(nèi)運(yùn)行WPF內(nèi)容和控件。一個(gè)簡單的比喻就是把WPF/e看成和在瀏覽器內(nèi)運(yùn)行的和Macromedia Flash或Apple QuickTime相似的技術(shù),其呈現(xiàn)的內(nèi)容比瀏覽器本身呈現(xiàn)得更豐富。就WPF/e來說,將被提交的內(nèi)容將是WPF應(yīng)用程序。WPF/e支持的功能是WPF API全部性能的子集,而且也不是最終決定下來的。但是我期望這些性能與我前面談到得XAML瀏覽器應(yīng)用程序的性能相似——你可以處理豐富的圖形,音頻,還可以呼叫回到原始網(wǎng)址(可能在宿主網(wǎng)頁內(nèi)使用AJAX技術(shù)),但是與訪問其他資源無關(guān)。然而,擁有一個(gè)好的從宿主站點(diǎn)顯示服務(wù)的分布式結(jié)構(gòu)能讓你使用WPF/e實(shí)現(xiàn)許多功能。請關(guān)注更多即將發(fā)布的與WPF/e有關(guān)的信息。
開發(fā)WPF應(yīng)用程序
根據(jù)應(yīng)用程序要做的任務(wù)來開發(fā)WPF的應(yīng)用程序,可以選擇純代碼方法,XAML代碼方法或者兩者的結(jié)合方法。后者將是最通用的,因?yàn)椴捎眠@樣方法,你可以從這個(gè)設(shè)計(jì)工具中得到最大的利益,可維護(hù)性,靈活性,而且使你的代碼更有表達(dá)力?;旧希阍赪PF中所作的一切僅僅是針對WPF .NET類庫中類型的代碼,因而代碼整個(gè)范圍的功能性對你是可用的。使用XAML操作接口讓你把可以更公開表達(dá)的對象設(shè)置在一種形式中,這種形式更方便于設(shè)計(jì)工具和設(shè)計(jì)者操作和定義。
一個(gè)WPF應(yīng)用程序由一個(gè)層次的元素構(gòu)成。最高等級(jí)的基本編程模式和Windows Forms并非很不相同。你創(chuàng)建一個(gè)應(yīng)用程序類別的實(shí)例,從Windows類別(或一個(gè)派生類別)創(chuàng)建一個(gè)最高等級(jí)的窗口,并運(yùn)行這個(gè)程序。和VB Windows Forms應(yīng)用程序一樣,如果你沒有明確地創(chuàng)建一個(gè)你自己的進(jìn)入點(diǎn),這個(gè)進(jìn)入點(diǎn)(主方法)將自動(dòng)產(chǎn)生。
例如,在下面圖2中的兩個(gè)XAML文件公開創(chuàng)建了一個(gè)應(yīng)用程序類實(shí)例和一個(gè)窗口類實(shí)例。這個(gè)窗口有它的第一個(gè)子要素作為網(wǎng)格。在WPF中,這個(gè)網(wǎng)格控件就像一個(gè)HTML表格或使Windows Forms2.0中的表格設(shè)計(jì)面板。它僅能提供給你一個(gè)矩形網(wǎng)格容器,你能夠把其他元素放置在里面用于設(shè)計(jì)。在網(wǎng)格之內(nèi),XAML定義了兩行兩列,然后使用附加屬性放置兩個(gè)文字塊控件和兩個(gè)文本框控件在這個(gè)網(wǎng)格單元中。
// 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>
產(chǎn)生的應(yīng)用程序如圖2所示。這個(gè)窗口顯示了Windows Vista邊框和標(biāo)題欄風(fēng)格,那是我一直用的。
如果在Windows XP和Server 2003上運(yùn)行,將會(huì)有這些操作系統(tǒng)的標(biāo)準(zhǔn)標(biāo)題欄和邊框風(fēng)格。
圖3運(yùn)行XAML應(yīng)用程序
同樣的應(yīng)用程序能用純代碼的方式來表示。
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實(shí)際上更加緊湊。因?yàn)橥ㄟ^XML內(nèi)聯(lián)屬性很多屬性能夠單獨(dú)的被設(shè)置而不需要單獨(dú)的一行代碼來設(shè)置。同樣的,你不必加入一個(gè)元素作為另一個(gè)元素的子元素,因?yàn)樵诳蓴U(kuò)展應(yīng)用程序標(biāo)記語言XAML標(biāo)簽的嵌套里,那種關(guān)系是隱式的。
你也可以從代碼看到由XAML產(chǎn)生的成分并非完全不同于你在Windows Forms或者ASP.NET中所做的。這個(gè)窗口是最高層元素,增加網(wǎng)格作為子元素,加文本塊和文本框控件作為網(wǎng)格的子元素等等。
當(dāng)你開始連接事件處理器控制事件時(shí),你經(jīng)常會(huì)通過C#或VB代碼來實(shí)現(xiàn)。XAML代碼編譯成一個(gè)部分類,你可以通過另一個(gè)部分類文件加任何代碼到這個(gè)部分類中。在這一點(diǎn)上,Visual Studio遵循一種同樣的ASP.NET方法,它為操作接口創(chuàng)建一個(gè)Window1.XAML文件,并在部分類中為代碼隱藏創(chuàng)建一個(gè)Window1.XAML.cs文件。
另一件你可能嘗試?yán)斫獾氖虑槭荴AML屬性或者代碼行,在那里,你明確指明包含的控件在哪一行、哪一列。這樣做用到了WPF中的一個(gè)新的概念,附加屬性。在XAML中,看上去有稱為Grid.Row和Grid.Column的屬性,Grid.Row和Grid.Column定義在控件類上。為每一個(gè)他們能用到的可能的文本中的控件明確地定義屬性,會(huì)導(dǎo)致對象模型混亂。但是,單獨(dú)的代碼版本讓我們更清楚實(shí)際上什么正在運(yùn)行。附加屬性要求網(wǎng)格上的動(dòng)態(tài)方法建立一個(gè)與被包含的控件相聯(lián)系的網(wǎng)格級(jí)的屬性。如果你接觸過Windows Forms擴(kuò)展提供控件,其概念和這里的是相似的。
建立更復(fù)雜的WPF應(yīng)用程序遵循你在這里所看到的相類似的模式。定義層次結(jié)構(gòu)上的更多元素,此層次結(jié)構(gòu)包括你的應(yīng)用程序的窗口。這些元素可能是容器控件的任何組合,例如網(wǎng)格,個(gè)別控件比如文本框,式樣,幾何,動(dòng)畫時(shí)間標(biāo)尺和情節(jié)串連圖板,3維模型,視頻等等。