程式效果 最終得到程式的運行效果如圖。拖動Slider可以使按鈕的背景色出現相應變化。 需求分析和架構設計 如果是你,接到了這樣的一個程式設計要求,會怎樣思考?第一步當然是需求分析啦。這個程式相對簡單,需要分析的主要是各個控制項之間的數據聯繫。這主要體現在Slider, Textbox和Button間
程式效果
最終得到程式的運行效果如圖。拖動Slider可以使按鈕的背景色出現相應變化。
需求分析和架構設計
如果是你,接到了這樣的一個程式設計要求,會怎樣思考?
第一步當然是需求分析啦。這個程式相對簡單,需要分析的主要是各個控制項之間的數據聯繫。這主要體現在Slider, Textbox和Button間的同步關係上:
拖動Slider的滑塊,要求TextBox里的數值也要變化,同時Button的背景色也要發生相應變化。改變TextBox里的值,滑塊的位置和Button的背景也要做相應調整。
一個習慣於WinForm的同學就會有很自然的想法——處理消息(.NET表現為事件)唄。對Slider滑塊的滑動這個事件,設置一個EventHandler,以更新Textbox的Text屬性和Button的Background屬性。對於Textbox.Text的更改這個事件,設置一個EventHandler,更新Slider的Value屬性和Button的Background屬性。
很好。下麵我們就來看一下在WPF中,思維可以變得如此不同而簡單。
實現過程
第一步自然是創建工程。首先在Visual Studio 2008下,新建一個工程,選擇Visual C#裡面的WPF Application即可。
稍等片刻就可以看見一個工程被創建,同時預設的窗體設計文件Windows1.xaml被顯示出來了。註意雖然XAML中可以像MFC那樣用圖形化的方式放置控制項,但是由於XAML的功能太強大,圖形化界面很難完全表達,因此在目前的版本中主要還是採用代碼的方式進行界面設計。不過微軟已經放風說在Visual Studio 2010中這樣的情況會加以改善。
第二步是設計UI。首先在XAML代碼中<Grid></Grid>間插入:
這一段代碼主要是將整個界面唰唰切成5行3列一共15個大塊,在設計界面中可以很清楚的看到(如下圖)。其中最左邊和最右邊這兩列固定為50像素,中間那一列是寬度可變的。
下麵就要往裡面放控制項了。在</Grid.ColumnDefinitions>和</Grid>間繼續加入以下代碼:
<TextBlock Grid.Column="0" Grid.Row="0">Red</TextBlock> <Slider Grid.Column="1" Grid.Row="0"/> <TextBox Grid.Column="2" Grid.Row="0"/>這是在第一行的第一個格子里放了一個TextBlock控制項,用來顯示那個Red。然後在同一行的第二個格子里放了一個Slider,第三個格子里放了一個TextBox。現在設計界面是這樣的:
看起來好醜哦。沒關係我們來修飾一下。
首先視窗太大了,把XAML文件中第四行中Window1的Height改成200先。然後每個控制項把格子占得滿滿的,影響美觀。在各個控制項中加入Margin="5",比如Slider控制項的代碼現在看起來應該是這樣的:
<Slider Grid.Column="1" Grid.Row="0" Margin="5"/>
這樣就使得空間和格子間有一定的間距,看起來舒服一點。
然後將各個控制項的垂直對齊方式設為中間對齊,加入VerticalAlignment="Center"即可。好的,現在蠻漂亮的了。
代碼看起來應該是這樣:
<TextBlock Grid.Column="0" Grid.Row="0" Margin="5" VerticalAlignment="Center">Red</TextBlock> <Slider Grid.Column="1" Grid.Row="0" Margin="5" VerticalAlignment="Center"/> <TextBox Grid.Column="2" Grid.Row="0" Margin="5" VerticalAlignment="Center"/>下麵我們來加入其餘三個TextBlock, Slider和TextBox。分別代表Green, Blue, Alpha值。將以上代碼複製粘貼三份即可。註意每一行都要相應修改Grid.Row值。第二行為1,以此類推。不要忘了把後面幾行TextBlock里的Red改成相應的Green, Blue等等哦。現在界面看起來像這樣:
最後需要在最後一行加入一個Button。在</Grid>前添加如下代碼:
<Button Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="4" HorizontalAlignment="Center" Width="100" Margin="5"> <Rectangle Width="10" Height="10" Fill="Red"/> </Button>很容易看懂這是說要添加一個寬度100像素,水平中央對齊,在第5行的按鈕。按鈕的內容是一個長寬各為10,紅色的方形。只是要註意Grid.ColumnSpan="3"表示這一個控制項將占用3列的空間。
再把Window1的Title改成ColorChange。至此UI的設計就結束了。如下圖。
呼,界面設計說起來還是比較繁瑣的。終於進入WPF強大的地方了。首先是界面設計的時候註意到了嗎?Button的內容可以是一個方塊誒!如果我告訴你還能是其他控制項比如是一個slider外加一個TextBox呢?就像這樣:
要是在MFC裡面還不要搞死人。最簡單的情況是通過改CButton的bitmap來實現在按鈕上顯示圖片。就算只想在裡面嵌入一個Slider,就首先要繼承CButton類,然後廣大人民充分發揮聰明才智吧,拼死拼活總算搞出來一種控制項叫做CSliderButton。然後一拍腦袋,哎呀我搞錯了,其實我想嵌入一個TextBox的。好吧,大返工……但是在WPF里如此簡單,我們要做的僅僅是把<Rectangle />換成其他控制項就好了,比如<Slider />,或者另一個有複雜結構的<Grid>。是不是很神奇?
還有我們上面進行的UI設計相對MFC來說繁瑣很多,但是也要強大很多。這主要表現在視窗的大小被改變時。一個MFC對話框程式,如果沒有經過特別精心的設計的話,一旦視窗大小被拖動或者最大化,一坨控制項還像原來一樣分佈,擁堵在左上角,唉……但是上面設計出的WPF的程式就不會,控制項仍然會均勻分佈在視窗中。(你可以自己試試看,如果覺得還是不夠完美可以自己想想怎樣再改動呢?)
下麵進入消息處理階段了,如果還可以這樣稱呼的話。第一步要把Slider和TextBox中的內容關聯起來。為了以下程式設計的方便,我們必須要先給各個控制項起個名字。在第一行的Slider裡面添加Name屬性,叫它ColorSliderR好了!也就是說,在<Slider ... />中加入Name="ColorSliderR"
同樣的,我們給剩下各個slider起名叫做ColorSliderG/B/A。把那個Button稱作MainButton。
然後要調整Slider的屬性,否則沒有應用價值。在各個Slider的代碼裡加入Maximum="255" Minimum="0" Value="255"。這表示滑塊到達最右邊的時候表示255,最左邊表示0,初始值在255。那麼Slider的代碼看起來應該是這樣的:
睜大眼睛啦!WPF神奇的地方又來啦!什麼消息處理,這麼麻煩,走開!不就是同步嘛,把TextBox和Slider綁上不就得了。好的。在4個<TextBox ... />中加入代碼Text="{Binding Path=Value, ElementName=ColorSliderR}",註意ElementName的值要根據各個控制項改動哦。這樣就把兩個控制項Bind起來了。運行一下看看:
成功啦!簡單不?嘖嘖,還帶小數點的,真牛X。註意,如果想要通過改變文本框的內容來改變滑塊位置的話,需要在輸入完畢後切換一下焦點,也就是隨便點一下本視窗內的其他地方改動才會生效。
真麽快?都到第四步了。下麵就要改變背景色啦。XAML固然強大,但光玩控制項間的綁定沒意思,咱辛辛苦苦學的for啊while啊不都沒用了嘛。這下咱換種方式。把XAML和後臺代碼綁定起來。
為了實現這個目標,先要做一個橋梁——在XAML和後臺代碼間溝通的橋梁。終於輪到C#上場了,人家都急死了。右擊XAML設計界面,單擊View Code打開Window1.xaml.cs。啊,終於看到熟悉的using了,激動死了激動死了。
在public partial class Window1這個類的後面,也就是這個類的}的後面,相當於跟這個類併列的地位,不要搞錯了啊,插入一個類,代碼如下:
學過C#的對這個應該很熟悉,標準的事件處理方法。大意就是這個類裡面有一個屬性SliderValue。它一旦被更改了就會大叫:老大我被人動啦!然後——當然很多人根本不睬他,只有他的老大聽到了就會過來看看並作出相關操作。這是C#針對消息處理作出的語言內部的支持。
還有,不要忘了在最前面那一坨using的最後插入一句
using System.ComponentModel;這是為了提供對事件處理的支持。
有了這個類,橋架起來了,綁定就好辦了。當然一個控制項應該是和代碼中的一個對象綁定而不是和一個類綁定,所以叫你有面向對象程式設計基礎呢,否則對象啊類啊還不把你繞昏掉。對象自然只能在Window1類中定義。好的,在類中(具體位置隨便在哪,只要這個類裡面就好)加入
SliderCommunicator sliderCR, sliderCG, sliderCB, sliderCA;然後搞個函數把他們初始化一下,整個Window1類看起來應該是這樣的:
public partial class Window1 : Window { SliderCommunicator sliderCR, sliderCG, sliderCB, sliderCA; public Window1() { InitializeComponent(); } void InitDataBinding() { sliderCR = new SliderCommunicator(); sliderCG = new SliderCommunicator(); sliderCB = new SliderCommunicator(); sliderCA = new SliderCommunicator(); } }嗯嗯,很好,下麵我們就可以把XAML和C#綁起來了。兩步走,第一步,改改InitDataBinding函數,改成這樣: