WPF開發(fā)入門嘗試
01. 創(chuàng)建軟件雛形
這個雛形包括4個項目(Project):
一個主程序(WPF Application)項目,命名為:DataTracer
一個組件庫(WPF User Control Library)項目,命名為:K3UcLib
一個控件庫(WPF Custom Control Library)項目,命名為:K3CcLib
一個算法庫(Class Library)項目,命名為:K3Helper
作為入門,這看起來有點復雜,不過實現(xiàn)起來還算簡單。
菜單:File >New >Project…
菜單:File >Add >New Project…
THINKING:
通常,復雜是由簡單構(gòu)成的,只要我們合理的分解它;
復雜的設計,并不意味著復雜的實現(xiàn);同樣,簡單的設計,也不意味著簡單的實現(xiàn);
不過,沒有準備迎接復雜挑戰(zhàn)的簡單設計,卻通常是小小噩夢的開始。
F5 運行,看看結(jié)果!
02. 制作一個組件
我習慣將User Control稱為組件,將Custom Control稱為控件。
他們的區(qū)分,簡單說:User Control通常通過組合多個控件產(chǎn)生,Custom Control通常通過擴展單個控件產(chǎn)生。
現(xiàn)在,我們先制作一個準備用來替換現(xiàn)有窗口標題的組件,命名為:K3WindowHeader。
Project Add User Control,然后修改XAML,并編譯(Shift F6)
- <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue">
- <DockPanel LastChildFill="True">
- <Button Content="關(guān)閉" Width="75" Height="23" DockPanel.Dock="Right" />
- <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White"/>
- </DockPanel>
- </Border>
這個組件包括兩個控件Button,TextBlock。
CornerRadius用于設定Border四個角的弧度
= ”LeftTop, RightTop, RightBottom, LeftBottom”
DockPanel.LastChildFill,很有用的屬性。
注意DockPanel所包含組件的順序,并在組件中正確的使用DockPanel.Dock屬性。
在DataTracer中使用這個組件。
Project Add References,添加K3UcLib,然后修改MainWindow.XAML:
- <Window …
- xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib"
- WindowStyle="None"
- > xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib"
- WindowStyle="None"
- > xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib"
- WindowStyle="None"
- >
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <K3UcLib:K3WindowHeader Height="25" />
- </Grid>
將WindowStyle設為None,將窗口標題隱掉,從而為DIY新的窗口標題做好準備。
Height, Width可取值包括:
Auto(自適應),*(全部剩余),NaN(相當于Auto),數(shù)值
F5 運行,看看結(jié)果!
這個窗口怎么關(guān)掉?Alt + F4!
這個窗口好丑!別著急,如果你真的很急,可以先試著使用 Margin屬性及xxxAlignment屬性,調(diào)整一下位置(試一試我的調(diào)整,如下)。
- <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue" Margin="3,0,3,0">
- <DockPanel LastChildFill="True">
- <Button Content="關(guān)閉" Width="75" Height="23" DockPanel.Dock="Right" Margin="0, 0, 10, 0" HorizontalAlignment="Center" VerticalAlignment="Center" />
- <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" />
- </DockPanel>
- </Border>
F5 運行,看看結(jié)果!
03. 添加事件,關(guān)閉窗口
需求:當用戶點擊“關(guān)閉”按鈕時,關(guān)閉主窗口。
實現(xiàn):為“關(guān)閉”按鈕添加Click事件處理。有兩種實現(xiàn)方式:
(1) 通過XAML文件中實現(xiàn):<Button Name=”buttonClose” Content=”” ……Click=”buttonClose_Click” ……/>
(2) 通過后臺代碼實現(xiàn):this.buttonClose.Click += new new RoutedEventHandler(buttonClose_Click);
這里,我們采用后者,即后臺代碼方式,完整代碼如下:
- public K3WindowHeader() {
- InitializeComponent();
- this.Init();
- }
- void Init() {
- this.buttonClose.Click += new RoutedEventHandler(Button_Click);
- }
- void Button_Click(object sender, RoutedEventArgs e) {
- throw new NotImplementedException();
- }
注:
使用Init()方法,是為了使代碼整潔。
在你鍵入“+=”時,系統(tǒng)將為你自動生成事件代碼。你可以先修改所生成的事件處理方法的名字,然后再按“TAB”鍵,這樣就可以生成你想要的名字的方法。在這里,我將默認的buttonClose_click改為Button_Click。
接下來,我們添加事件處理的內(nèi)容,以實現(xiàn)關(guān)閉主窗體。
注意,因為我們使用的是另一個組件項目中的組件,而非主程序自身項目中的組件,所以實現(xiàn)起來稍微有點麻煩,不是簡單的一個Close()就可以完成。
在這種情況下,有多重實現(xiàn)方式:
(1) 假定組件自身知道自己是如何被使用的,如本案例中,它被放在主窗體的Grid中,那么可以這樣實現(xiàn):
((this.Parent as Grid).Parent as Window).Close(); 這種實現(xiàn)方式,屬于hard code,使組件失去了靈活性,不是一個好方法,但它是一個思路,即:只要你能找到你想要的,你就可以做你想做的。
(2) 將點擊“關(guān)閉”按鈕事件,轉(zhuǎn)化成一個新的事件,告訴引用這個組件的窗體:有人請求關(guān)掉你!這個設計有點麻煩,但使組件具有了組件該有的特性:靈活性,或稱為適應性,以保證你可以相對隨意的使用它。
#region >>>>> 自定義事件 ... public static readonly RoutedEvent PreviewWindowHeaderEvent; public event RoutedEventHandler PreviewWindowHeaderEventHandler { add { this.AddHandler(PreviewWindowHeaderEvent, value); } remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); } } static K3WindowHeader() { PreviewWindowHeaderEvent = EventManager.RegisterRoutedEvent( "PreviewWindowHeaderEventHandler", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(K3WindowHeader)); } #endregion …… void Button_Click(object sender, RoutedEventArgs e) { RoutedEventArgs eventArgs = new RoutedEventArgs(); eventArgs.RoutedEvent = PreviewWindowHeaderEvent; RaiseEvent(eventArgs); } |
這段代碼,加在K3WindowHeader中。 #region #endregion的合理使用,有利于提升代碼的可讀性。你可以加上注釋。BTW,我添加>>>>> … 是為了美觀,讀者可以試試去掉它,或改變它,看看你自己更喜歡哪一個。 注意,我添加了static 類型的構(gòu)造函數(shù),以便注冊自定義事件。 Event有兩種類型,其關(guān)鍵參數(shù)是:RoutingStrategy,其取值的不同,將生成兩種傳遞方向不同事件。詳述如下: |
|
public static readonly RoutedEvent PreviewWindowHeaderEvent; public event RoutedEventHandler PreviewWindowHeaderEventHandler { add { this.AddHandler(PreviewWindowHeaderEvent, value); } remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); } } static MainWindow() { PreviewWindowHeaderEvent = K3WindowHeader.PreviewWindowHeaderEvent.AddOwner(typeof(MainWindow)); } void Init() { this.PreviewWindowHeaderEventHandler += new RoutedEventHandler(CustomEventHandler); } void CustomEventHandler(object sender, RoutedEventArgs e) { this.Close(); } |
這段代碼,加在DataTracer中。 注意這段代碼與上段代碼的不同,在于靜態(tài)構(gòu)造中,我們通過事件的AddOwner方法,將這兩個自定義事件關(guān)聯(lián)起來,從而保證了可以捕獲到該事件。 同樣,我使用了Init來使代碼整潔,并在其中添加了對該特定事件的處理程序。別忘了將Init()放入構(gòu)造函數(shù)中。 |
F5 運行,看看結(jié)果!
原文鏈接:http://www.cnblogs.com/technology/archive/2011/04/19/2020910.html
【編輯推薦】