有時候在MSDN論壇或是社團中會看到有人在問:「為什麼要用WPF?」 、「為什麼要用Silverlight?」,也有不少人會問「Silverlight和WPF有什麼不同?」、「我到底應該使用WPF還是Silverlight?」等等問題。更深入一點的,還有朋友會問到「學WPF有前途嗎?」或是「學Sivlerlight有前途嗎?」之類的種種問題。
遇到這類問題的時候,我比較不喜歡直接點出哪種技術才是好的、哪種技術才是對的;基本上會有這些問題的朋友,應該只是很單純的對這兩種技術的認識還不夠。我想,直接從兩種技術的本質和特性下去先做個基本的了解,或許就能解決大部份的疑惑了。
有時候在MSDN論壇或是社團中會看到有人在問:「為什麼要用WPF?」 、「為什麼要用Silverlight?」,也有不少人會問「Silverlight和WPF有什麼不同?」、「我到底應該使用WPF還是Silverlight?」等等問題。更深入一點的,還有朋友會問到「學WPF有前途嗎?」或是「學Sivlerlight有前途嗎?」之類的種種問題。
遇到這類問題的時候,我比較不喜歡直接點出哪種技術才是好的、哪種技術才是對的;基本上會有這些問題的朋友,應該只是很單純的對這兩種技術的認識還不夠。我想,直接從兩種技術的本質和特性下去先做個基本的了解,或許就能解決大部份的疑惑了。
所以接下來,讓我來為有需要的朋友們先簡單的介紹一下這兩種技術吧!!
WPF
WPF的全名為Windows Presentation Foundation,是微軟用來解決Windows平台上的RIA應用程式的解決方案(可以把Adobe的AIR看作是它的對手),從.Net Framework 3.0版開始就被內建在.Net Framework之中(當時的版本就直接為 3.0版),目前最新的版本是4.0(內建在.Net Framework 4.0裡),而目前WPF版本幾乎都跟隨著.Net Framework一起更新。一般情況下,WPF編譯出來的檔案就像我們平常在使用的Word、Excel等等,是可以直接執行的exe檔。
Silverlight
Silverlight則是由WPF所衍生出來(一開始叫做WPF/e,e代表的是every where,強調可以跨平台執行),在Web上的RIA解決方案(想當然爾,它的對手是Adobe的Flash),目前正式發行的最新版也是4.0。不過,Silverlight版本的更新可就不是隨著.Net Framework一起更新喔(依照過去的經驗,通常會比.Net Framework還要晚一些)。一般情況下,Silverlight編譯出來的檔案副檔名會是xap,而且必需透過一個Html來當作宿主才能正常顯示。而Silverlight也是最近微軟強推的Windows Phone 7上可以用來開發應用程式的技術之一喔!!
以上就是對於WPF和Silverlight的簡短介紹,為了不讓大家覺得太複雜,所以請有興趣研究它們各自的歷史演進的朋友們自行前往維基百科或是MSDN、Silverlight官網查詢喔!!基本上,如果您要使用的執行平台是Windows,那就可以使用WPF;如果希望應用程式在Web上跑,那就可以使用Silverlight。
那麼,要開發WPF或是Silverlight應用程式,應該要會哪些程式語言,還有必需要準備哪些工具呢? 基本上,這兩種技術都可以使用C#或是Visual Basic,再搭配用來描述使用者介面的XAML(eXtensible Application Markup Language)語言來進行開發。預設的WPF或是Silverlight的應用程式或是使用者控制項,都會是一個用來描述使用者介面的Xaml檔,配合一個(或多個)放程式碼的CodeBehind檔。而使用XAML的好處是:萬一日後有轉移平台的必要的話,只需小幅的修改XAML的內容,使用者介面就可以跨平台的被重複利用喔!!另外,原本許多在傳統的Windows Form及ASP.Net中得寫很多程式碼才能辦到的事,只要簡單的透過Xaml,就可以輕鬆完成喔!!
有在撰寫.Net的朋友們應該都對Visual Studio很熟悉,可以輕鬆的用它來撰寫CodeBehind的程式,而從Visual Studio 2010版開始,我們也可以透過它,以簡單的透過拖拉控制項的方式(就像編輯以前的Windows Form或是ASP.Net的頁面)來進行Xaml的編輯。
不過除了Visual Studio之外,微軟還推出了另一系列(就有點像Adobe的Creative Suite)的套裝軟體叫Expression Studio,裡面的Expression Blend則是可以幫助設計師用來設計WPF或是Silverlight使用者介面的好幫手喔!!它可以幫助設計師不用去熟背Xaml語法,直接透過工具,以熟悉的方式,製作出酷炫的使用者介面和動畫。
簡單來說,上面這一大段文字的重點如下:
給各位朋友們看兩個小小的範例,可能會比較有感覺(下面的兩個範例就都是透過Expression Blend以拖拉控制項和調整設定的方式做出來的,完全不用寫程式):
*若無法正常瀏覽本文WPF版範例,煩請參考[Windows7]使用IE9、FireFox與Chrome瀏覽WPF Browser Application(.XBAP)的方式一文調整瀏覽器設定
WPF | Silverlight |
而上面兩個範例的Xaml檔分別如下(其實內容幾乎一模一樣喔!!而且對有在寫xml或是ASP.Net的朋友來說,這樣的東西應該不會太難讀吧?!):
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="Wpf_SimpleSample.Page1"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400" ShowsNavigationUI="False" Title="Page1">
<Page.Resources>
<Storyboard x:Key="Storyboard1" AutoReverse="True">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="textBlock1">
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)"
Storyboard.TargetName="textBlock1">
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="360">
<EasingDoubleKeyFrame.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)"
Storyboard.TargetName="textBlock1">
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1.5">
<EasingDoubleKeyFrame.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)"
Storyboard.TargetName="textBlock1">
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="1.5">
<EasingDoubleKeyFrame.EasingFunction>
<QuadraticEase EasingMode="EaseInOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Page.Resources>
<Border BorderThickness="2" CornerRadius="10" Margin="10" Background="White" BorderBrush="#FF646464">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="0.253*" />
<RowDefinition Height="0.747*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="WPF小小範例"
VerticalAlignment="Center" FontSize="26.667" FontWeight="Bold" Foreground="#FF646464" />
<Rectangle Fill="#FF646464" Height="2" Margin="10,0" VerticalAlignment="Bottom" />
<Button x:Name="btnButton1" Content="Say Hi" HorizontalAlignment="Center" Grid.Row="3"
VerticalAlignment="Center" Margin="0,5" Padding="10,5" FontSize="14.667" FontWeight="Bold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ControlStoryboardAction ControlStoryboardOption="Stop"
Storyboard="{StaticResource Storyboard1}" />
<ei:ControlStoryboardAction ControlStoryboardOption="Play"
Storyboard="{StaticResource Storyboard1}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Center"
Margin="10,0,0,0">
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="請輸入您的大名:" VerticalAlignment="Center"
FontSize="14.667" />
<TextBox x:Name="textBox" TextWrapping="Wrap" VerticalAlignment="Center" Width="200" Margin="10,0,0,0" />
</StackPanel>
<TextBlock x:Name="textBlock1" TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0,0,-6,16"
d:LayoutOverrides="Height" Grid.Row="2" VerticalAlignment="Center"
Text="{Binding Text, ElementName=textBox, StringFormat=Hi!!~\{0\}}" FontWeight="Bold"
FontSize="18.667" Opacity="0" Foreground="#FF646464" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</TextBlock.RenderTransform></TextBlock>
</Grid>
</Border>
</Page>
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="SL_SimpleSample.MainPage"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<Storyboard x:Name="Storyboard1" AutoReverse="True">
<DoubleAnimation Duration="0:0:2" To="1" Storyboard.TargetProperty="(UIElement.Opacity)"
Storyboard.TargetName="textBlock1" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Duration="0:0:2" To="360"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.Rotation)"
Storyboard.TargetName="textBlock1" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Duration="0:0:2" To="1.5"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)"
Storyboard.TargetName="textBlock1" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimation Duration="0:0:2" To="1.5"
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
Storyboard.TargetName="textBlock1" d:IsOptimized="True">
<DoubleAnimation.EasingFunction>
<QuinticEase EasingMode="EaseInOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</UserControl.Resources>
<Border BorderThickness="2" CornerRadius="10" Margin="10" Background="White" BorderBrush="#FF646464">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="0.253*" />
<RowDefinition Height="0.747*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="Silverlight小小範例"
VerticalAlignment="Center" FontSize="26.667" FontWeight="Bold" Foreground="#FF646464" />
<Rectangle Fill="#FF646464" Height="2" Margin="10,0" VerticalAlignment="Bottom" />
<Button x:Name="btnButton1" Content="Say Hi" HorizontalAlignment="Center" Grid.Row="3"
VerticalAlignment="Center" Margin="0,5" Padding="10,5" FontSize="14.667" FontWeight="Bold">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:ControlStoryboardAction ControlStoryboardOption="Stop"
Storyboard="{StaticResource Storyboard1}" />
<ei:ControlStoryboardAction Storyboard="{StaticResource Storyboard1}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Grid.Row="1" VerticalAlignment="Center"
Margin="10,0,0,0">
<TextBlock x:Name="textBlock" TextWrapping="Wrap" Text="請輸入您的大名:" VerticalAlignment="Center"
FontSize="14.667" />
<TextBox x:Name="textBox" TextWrapping="Wrap" VerticalAlignment="Center" Width="200" Margin="10,0,0,0" />
</StackPanel>
<TextBlock x:Name="textBlock1" TextWrapping="Wrap" HorizontalAlignment="Center" Margin="0,0,-6,16"
d:LayoutOverrides="Height" Grid.Row="2" VerticalAlignment="Center"
Text="{Binding Text, ElementName=textBox, StringFormat=Hi!!~\{0\}}" FontWeight="Bold"
FontSize="18.667" Opacity="0" Foreground="#FF646464" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<CompositeTransform />
</TextBlock.RenderTransform></TextBlock>
</Grid>
</Border>
</UserControl>
再來,簡單的說明一下兩種技術的執行平台和限制。在執行的平台上的差異,要執行WPF的話,基本上就得安裝.Net Framework(或是最基本的Client Profile),而要執行Silverlight的話,則只需要安裝Silverlight的Runtime plug-in就行了;就如同前面介紹的,因為WPF內建在.Net Framework之中,因此WPF幾乎可以透過.Net Framework中原生的功能,去存取作業系統中的資源。而Silverlight呢;因為它的主力放在Web上,而Web應用程式基於安全性等等的相關考量,使用Silverlight時要存取作業系統中的資源,就沒那麼方便直接了。
誠如以上的列舉的條件,如果您的應用程式得透過作業系統和許多其他的硬體設備溝通、得要大量的讀寫檔案、或是您的應用程式想要內嵌已經開發完成的Windows Form;更甚者,如果您的應用程式需要使用到以C++或是C開發出來的元件,那麼,使用WPF將會比較輕鬆。如果沒有前面提到的相關需求,而且希望將應用程式建立在Web上的話,那就可以考慮使用Silverlight。
不過;WPF也有可以透過瀏覽器當作宿主的變形版本,叫做WPF Browser Application,其產出的檔案副檔名為xbap(像上面的WPF範例就是);而Silverlight呢?也出現了可以像一般應用程式一樣直接安裝在作業系統中執行的OOB(Out of browser)版本,許多原先在Silverlight中有的限制,都可以透過轉成OOB模式來解除(例如存取我的文件資料夾,或是和部份的Com+元件溝通等等)。不過,如果要使用WPF Browser Application或是Silverlight的OOB,就得注意使用者端憑證(WPF Browser Application)和信任(Silverlight OOB)的問題喔!!
基本上,不管是學了WPF或是Silverlight,再來要再學另一項,就會非常的快速了,因為使用的語言幾乎是一樣的,只是原生提供的控制項和能使用的API會有些差別而已,甚至之後如果有興趣開發Windows Phone上的應用程式的話,也是得使用Silverlight來開發,所以學了一種,要再進入另外的兩個平台就會相對的快速啦!!
最後,有些朋友會問,到底我用Windows Form開發和用WPF開發的應用程式有什麼不一樣?而用ASP.Net開發和用Silverlight開發的應用程式又有什麼不一樣呢? 到底什麼時候該轉戰WPF和Silverlight的戰場,或是繼續使用原來的技術就好呢?
以下是我的真心話:
技術沒有分好或壞,單單看使用的人怎麼去用它。當然,一定有高手可以用傳統的Windows Form或是ASP.Net寫出跟WPF或Silverlight一樣華麗的使用者介面;但是也會有人使用WPF或是Silverlight,可是做出來的東西和傳統的Windows Form或是ASP.Net開發出來的東西沒什麼兩樣的。這個時候,究竟要不要用新技術,單看有沒有一顆求新求變的心和有沒有一顆富有創意的腦袋了。
微軟提出的RIA精神,Rich和Interactive,就看我們怎麼去實踐囉!!