WPF四年,尤不足以替代WinForm

WPF四年,尤不足以替代WinForm

WPF出山已四年,作爲官方內定的下一代UI系統掌門,沒少露臉。但這個新掌門能否勝任,仍是衆多開發者的心頭之慮。通過對VisualStudio 2010的編輯器部分用WPF重寫,微軟終於對這個勝任與否的問題給出了個證實,當然,也給WPF做了不少重要的改進,尤其是終於解決了文本看不清的問題。所以,至少從.NET 4開始,WPF應該可以比較安全的用於重要的開發項目了。

但是,使用WPF並不會象用WinForm那樣順利。

首先,它太複雜了,入門門檻很高。這種複雜性一定程度上源於它統一桌面和Web開發的野心。用一套Framework來同時支持桌面和Web,固然很好,但也同時繼承了兩者的複雜性。如果既有WinForm又有ASP.NET開發經驗的話,就會覺得這種合併很自然,有前途。當然,WPF還有更高的目標,就是挑戰Flash。這種以一當三的精神固然可嘉,可以想象同時擊敗三派風格迥異的武林掌門的話會有多強大。但對我們學、用WPF的開發者而言,有多少人是要同時針對兩個甚至三個領域的?即使只需面對其中一個領域,我們也得面對WPF的全部複雜度。當然,也有潛在的好處,可以輕鬆的引入另外兩個領域的技術。

其次,對WinForm開發者而言,入門WPF可能還要更困難,因爲最基本的東西——製作界面的XAML,完全是Web式的風格和思路。原來WinForm的知識和技能,大部分都不再適用。一開始就要面對的選擇是Document、Window、Page、NavigationWindow等,而不是一個簡單的Form。創建Window後,如果指望象WinForm那樣設計窗體,就會發現它的窗口設計器基本是個笑話,還是老老實實地手寫XAML吧,這時會慶幸自己還曾學過點HTML。如果無法忍受手寫XAML,那麼可以下載Expression Blend,類似於Flash編輯器,這時會慶幸自己還曾搞過那麼點美工,會用Flash。

之後,會發現加個Tool Button竟然不能直接同時指定圖標和文本,還必須嵌套一層StackPanel;Disable時圖標不會變灰,需要自己寫Style來實現;ToolBar末尾的Overflow popup按鈕總是顯示很討厭,要隱藏就得在ControlTemplate上最手腳;DropDownButton也沒有,要自己實現……不少WinForm裏習以爲常的東西,突然都沒有了。雖然通過強大的Style系統和Composition都能實現,但畢竟是要費額外的功夫。

Resource的添加和管理比以前倒是簡單了,只要把文件加入project裏,自由組織目錄結構,把文件的Build Action設置成Resource就行了。但是引用資源文件的路徑就搞惡了,不知道是哪個精神異於常人的傢伙發明了這個Pack URI的規則(形如pack://application:,,,/ReferencedAssembly;v1.0.0.1;component/MyResourcePath/ResourceFile.xaml),一看見我就想打沙包。所幸多數情況下只需要相對路徑,可以省略前面那串欠扁的東西。

數據綁定算是編程模式上最大的改變之一了,與UI的數據交互幾乎全部通過綁定來實現,簡單的情況會很簡單,很強大,比WinForm裏的數據綁定強多了。但複雜的情況就讓人撓頭了。稍微複雜一點就必須寫個ViewModel層,也就是要寫個介於UI和業務邏輯之間的交互類,UI都綁定到這個類的屬性上。之後要考慮的是數據顯示的格式化問題,比如如何把一個浮點數顯示成百分數輸出;組合多個屬性合併成一個輸出的問題;還有用戶輸入的合法性校驗問題;限制可輸入字符的問題;想要在按回車鍵時接受處理輸入的問題……這些都不是直接了當有現成支持的問題,需要自己寫些代碼來解決。

除此之外,WPF的語言本地化工具支持基本等價於零,只有複雜難用的命令行工具,還是SDK的sample編譯的。要做本地化翻譯基本只能靠第三方工具。

更有趣的是,WPF程序缺省使用en-US的Culture,而不管當前系統的Culture是什麼,需要自己寫代碼在程序啓動時設置Window或控件的Language屬性,或者Override它的FrameElement.LanguageProperty的MetaData裏的缺省值。當然,這個不是bug,而是by design。其原因來自最早.NET的一個設計錯誤。

 

當年最初設計.NET時,他們計劃將全球化和本地化支持從基礎庫部分開始支持,以便使之適應未來越來越全球化的市場,於是所有的字符串格式化函數都是缺省使用當前系統culture的。但此時所有其他開發語言裏,缺省都是en-US標準。結果,大量的程序並未考慮這種差異,其結果一是性能損失,考慮本地化的字符串處理的開銷要比簡單的二進制字符串處理慢很多,二是導致了大量在不同語言系統上會出現的bug。比如,在德文系統上生成個浮點數“1.23”文本,出來是“1,23”,發送到英文系統上讀取,就解析出錯了。再比如,不同語言的大小寫對應是不同的,轉換大小寫在不同語言的系統上可能得到不同的結果,在文件名、路徑處理上會導致意想不到的bug。開發.NET 2.0時,.NET的開發者們已經意識到了這個錯誤,但已經不能更改已有的API了,於是只能爲這些函數增加了帶新參數的重載,並推薦大家不要再用舊的API,而要用這些寫起來非常長的函數,如string.Equals(string another, StringComparison comparisonType),用string.Format()時也最好用指定Culture的那個重載,充分利用CultureInfo.InvariantCulture。WPF的設計者們充分吸取了這個教訓,所以缺省總是en-US,需要本地化的地方要顯示指定。

再之外,ILMerge是不能正確合併WPF的assembly的,因爲它不能修正baml裏對資源的引用字符串。也就意味着,基於ILMerge的obfuscator也有這個問題。不過對Obfuscator而言,要支持WPF本身就不是件容易的事。因爲WPF依賴與數據綁定,數據綁定裏大量用對象屬性的名字字符串,而編譯之後XAML會被編譯成二進制的BAML,而BAML的格式是非公開的。這樣就不能去改被引用的對象屬性名。

總而言之,WPF還有很多路要走,前途是光明的,道路是曲折的。未來是WPF的,也是WinForm的,但歸根結底都是韓國人的?

發佈了118 篇原創文章 · 獲贊 137 · 訪問量 50萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章