一、什么是控件呢?
控件要滿足三個條件:
- 它是相對獨立的模塊,這些模塊可以通過一定的方式(通常是排版)像堆積木似的組合起來;
- 它具有對用戶輸入反應的能力,用戶輸入經由Windows操作系統的消息機制而轉換為控件事項;
- 每個控件具有特定的圖形表現形式,由於WPF把控件的特性和控件的顯示方式分開,過去由顯示方式區分控件的界限有時候不是很清晰的。
WPF空間類繼承圖:
控件都是從Control類中派生出來的,基本上可以分為4類:
● 內容控件(Content Controls)
● 條目控件(Items Controls)
● 文本控件(Text Controls)
● 范圍控件(Range Controls)
二、內容控件(Content Controls)
內容控件是WPF控件中的一大類,ContentControl直接從Control類中派生出來。
內容控件的最大特征是這類控件都含有一個Content屬性,即它只能有一個直接的子控件,這個Content屬性的類型為Object。
1.框架控件(Frame)
框架控件的主要作用是把其中的內容和界面上其他部分分開,它里面可以含有任何東西,但只能有一個直接的子控件。雖然Frame可以是其他控件的子控件,但是其宿主包容器的相關屬性不會傳遞到Frame中,即起到隔離的作用,即Frame控件“阻斷”了相關屬性的傳遞。
這個控件有個好玩的地方,可以嵌入一個網址。
通常使用Frame控件的目的是要在其中嵌入HTML內容;
在Frame中加入HTML非常簡單,只要設定Source屬性就可以了。
2.WPF按鈕(Button)
WPF中的按鈕都是從ButtonBase抽象類中派生出來的。
ButtonBase中定義了四個屬性
以ButtonBase為基類的有四個類:Button、GridViewColumnHeader、RepeatButton和ToggleButton。其中GridViewColumnHeader控件,筆者將在討論GridView控件時一並討論;從ToggleButton中派生出兩個著名的按鈕控件:RadioButton和CheckBox。
按鈕Button
按鈕是Windows用戶界面程序中最常用的控件。
3.撥動按鈕(ToggleButton)
撥動按鈕的特性就像撥動開關一樣,把開關撥到一個位置,燈亮了;把開關撥到另一個位置,燈滅了。撥動按鈕也是這樣,按一下撥動按鈕,其IsChecked屬性變為True;再按一下撥動按鈕,其IsChecked屬性變為False。
有時,我們需要撥動按鈕維持三個狀態,這時我們把IsThreeeState屬性設為True。在IsThreeeState屬性設為True時,IsChecked的屬性值可能取三個值:True,False和Null,ToggleButton中的事件。
一般並不直接創建ToggleButton實例,而是使用其派生類:CheckBox和RadioButton。
4.CheckBox控件
CheckBox控件用在可以有多個選項,而又可以同時選擇兩個或兩個以上選項的情況下。比如說,某個專業一學期開了八門課,其中有兩門是必修課,其余都是選修課,那么這個時候就可以把這六門選修課用CheckBox表現出來,供同學們選擇。
CheckBox並沒有增加任何屬性,它為ToggleButton提供外觀。
5.RadioButton控件
RadioButton控件若在一組選項里面,你必須而且只能選擇一個選項,需要使用RadioButton。比如,要調查某一類消費者使用你的產品,就需要知道消費者的性別、年齡組等,這時RadioButton就是最好的選擇。因為一個人要么是男的,要么是女的。
就像前面所說的“你必須選擇一個”,RadioButton並不提供“不選”操作,要去掉某個選項的方法是選擇另一個選項。所以,需要把相關選項放到一個組里。WPF的RadioButton增加了一個屬性:GroupName,其類型為字符串string。
6.重復按鈕(RepeatButton)
重復按鈕是WPF新增的一個控件,和一般的按鈕不同,重復按鈕可以在按下鼠標左鍵時,不停地發出單擊Click事件。這種特性在某些情況下是很有用的,比如DVD機上的快進或快退鍵。在按下快進鍵的時候,DVD中的內容會快速地播放出來,還可以選擇以2倍、4倍、8倍或更高速率播放,從而更快地找到所要找的內容。
重復按鈕實現了這種功能,它增加了兩個屬性:Delay和Interval。
● Delay這個屬性設置從用戶按下鼠標左鍵到開始重復發送Click事件的延遲時間。單位為毫秒(ms),Delay的數值必須大於等於0。
● Interval這個屬性設置當用戶按下鼠標左鍵時,每次發出Click事件的時間間隔。單位為毫秒(ms),Interval的數值必須大於等於0。
7.帶有標題欄的內容控件(HeaderedContentControl)
帶有標題的內容控件(HeaderedContentControl)除了具有內容控件的Content屬性之外,加入了一個新的標題屬性(Header)。Header的類型和Content一樣,都是Object,換句話說,任何.NET對象都可以成為標題Header。當然最常用的標題是字符串,但也可以是任何其他控件或控件的組合。
若不用標題內容控件HeaderedContentControl,也可以很容易用其他控件的組合來達到同樣的效果。確實,通常使用的不是HeaderedContentControl控件本身,而是它的兩個派生類:分組框和伸展控件。
8.分組框(GroupBox)
分組框(GroupBox)是一個常用的控件,在Win32里就有這樣的控件。其用法是把一些意義相近的控件放在一起,同時用一個帶標題的邊框把它們組合起來。
9.伸展控件(Expander)
伸展控件是Win 32中沒有的一個控件,它在壓縮時,只顯示標題;在展開時才顯示其中的內容。所以,使用這個控件可以在很小的版面上顯示更多的內容。現在很多網頁已經使用了這種控件,WPF對這一控件進行了標准化。
伸展控件增加了兩個相關屬性,一個是ExpandDirection,其類型為枚舉類型,可取Up、Down、Left、Right四個值;另一個是IsExpanded,其類型為布爾值,當該值為True時表明伸展控件處在展開狀態。
10.標簽控件(Label)
標簽控件也是一個常用的控件,這個控件就是在窗口的某個地方顯示字符串,這里的某個地方通常是由控制版面控件安排的。
標簽控件是一個內容控件,與所有的內容控件一樣,可以把它設為任何WPF控件及其組合,但我們最常用的標簽控件的功能是顯示字符串。在WPF里,Text-Block和TextBox等都可以用來顯示字符串。
標簽控件區別於TextBlock和TextBox的功能主要有兩點:
1.在默認的情況下,標簽控件是只讀的,顏色是灰色的;
2.標簽控件內置了一個AccessText控件,可以直接設定熱鍵到目標控件。
11.為按鈕設置熱鍵
使用AccessText設置熱鍵非常簡單,即在字母前加一下畫線即可。
<AccessText>我有熱鍵P(_P)</AccessText>
在使用中文時,一般不會遇到字母前用到下畫線的情況,但在英文里會遇到字符串本身有下畫線,而不是熱鍵的情況。這時,我們需要加兩個
下畫線:
<AccessText>This _is Really cool!</AccessText>
12.ToolTip
ToolTip通常是程序員在某些用戶界面元素上加入的幫助信息,過去常用在工具條上。
例如,在Microsoft Word軟件中,當把鼠標移到工具條的某個按鈕上時,在按鈕的下面會顯示一個矩形框,矩形框里顯示該按鈕的功能提示信息。當鼠標離開該按鈕時,這個矩形框會自然消失,這就是我們常說的ToolTip。過去ToolTip控件相對簡單,通常只能顯示簡單的文字信息,MFC里的CtoolTipCtrl就是這樣的控件。
而WPF中的ToolTip控件功能則強大靈活得多:首先,ToolTip屬性是定義在FrameworkElement類和FrameworkContent中的,這意味着不僅WPF中的所有控件都可以使用ToolTip,而且圖形和文檔也可以有ToolTip。其次,ToolTip和其他WPF內容控件一樣,其中可以含有其他任何WPF控件及其組合。
使用ToolTip需要注意下述兩點:
- ToolTip雖然是一個控件,但其本身不具備接收用戶輸入的功能。比如上面的例子中,在ToolTip中使用了ListBox,你就無法像通常ListBox那樣選擇其中的條目。
- ToolTip雖然是一個控件,但它不能像其他控件那樣作為其他控件的子控件,它必須和某個控件的ToolTip屬性相連。當鼠標離開控件時,其ToolTip會自動隱藏。
有時候,你希望控制ToolTip的顯示時間,ToolTipService類就是為此設計的,該類含有控制ToolTip的附加屬性,如控制ToolTip水平或豎直方向位移的屬性HorizontalOffset、VerticalOffset;控制ToolTip顯示時間的ShowDuration屬性;控制是否在未使能的控件上顯示ToolTip的ShowOnDisabled屬性等。
13.ScrollViewer
當窗口中的內容比窗口的大小要大時,通常要在窗口中顯示滾動條。在WPF中顯示滾動條要用到ScrollViewer類,這是一個內容控件,和所有的內容控件一樣,它只能含有一個子控件。
使用LineBreak控制句子的分行。
三、條目控件(Items Controls)
ItemsControl,它是直接從Control類中派生出來的。與內容控件中只能含有一個控件不同,ItemsControl中含有Items屬性,這個屬性具有ItemCollection類型。
在內容控件中,其內容可以是任何一個Object類型的對象;在Items屬性中則可以加入任何一個Object類型的對象。
WPF在顯示Items屬性中的對象時,如果這個對象是UI元素,就直接調用UI元素的OnRender方法;如果這個對象不是UI元素,WPF會創建一個TextBlock,並在TextBox中顯示該對象的ToString方法所返回的結果(由於在.NET中所有的類都從Object類中派生出來,而Object類中含有ToString方法,所以,調用ToString方法是不會有什么問題的)。
除了可以加入任何.NET對象的Items屬性之外,ItemsControl類中還有一個重要的屬性ItemsSource,這個屬性是用來作數據綁定的。需要注意的是,一旦我們使用了ItemsSource屬性,Items屬性就會被自動設置為null。這表明只能使用ItemsSource和Items兩個屬性當中的一個,而且ItemsSource具有更高的優先級。
1.菜單(Menu)
菜單是一個常用的控件,常位於應用程序窗口的頂部。每個菜單里面含有菜單條目(MenuItem),MenuItem是一個帶有標題的條目控件,它從HeaderedItemControl類中派生出來。HeaderedItemControl類中有一個類型為Object的屬性:Header,在菜單條目中通常把它設為字符串。有時候菜單條目下會有子菜單,子菜單的條目下還會有下一層的子菜單,等等。
這里的InputGestureText只負責顯示熱鍵信息,要是熱鍵工作,需要用到命令Command屬性。
為方便程序員快速開發界面,WPF定義了一個ApplicationCommands的類。ApplicationCommands類中定義了編輯軟件常用的命令,這些命令有:Close、Copy、Cut、Delete、Find、Help、New、Open、Paste、Print、PrintPreview、Redo、Replace、Save、SaveAs, SelectAll、Stop、Undo等。當ApplicationCommands和菜單相連,它還具有自動Enable/Disable菜單條目的功能。
彈出菜單(ContextMenu)
與下拉菜單和排版類相連不同,彈出菜單則要附加在UI元素的ContextMenu屬性上。FrameworkElement里面有一個ContextMenu屬性,程序員所要做的就是構建彈出菜單,並在相應的UI元素上設置ContextMenu屬性。由於FrameworkElement是所有UI元素的基類,所以,WPF在廣泛的范圍內支持彈出菜單。
ColorBox類從ListBox中派生出來,首先用UniformGrid作為ListBox的ItemsPanel。再在ListBox的Items屬性中加入矩形,矩形的顏色是預定義的。這樣,ColorBox就會顯示預定義的顏色供用戶選擇。
2.工具條(ToolBar)
過去工具條和菜單常常一起用在應用程序中,比如Microsoft Office軟件,位於視窗標題欄下面的是菜單,菜單下面就是工具條。有時候,工具條位於一個浮動窗口內,這樣用戶可以把工具條停靠在屏幕的任何位置。與菜單相比,通常只要在工具條上單擊鼠標一次就可以完成某個功能,而菜單通常要單擊兩次或以上;工具條使用圖標加ToolTip的方式,在屏幕上要占據較大的位置,所以只適合把常用的菜單功能放在工具條上。
3.Selector
Selector類是下面三個條目控件的基類:
● ComboBox
● ListBox
● TabControl
這三個控件共同的特點是:其中包含一個或多個條目供用戶選擇。而這個共同的特點,自然地就移植在它們的基類——Selector類中。ListBox控件還有一個派生類——ListView,它自然地繼承了Selector類中所移植的特性。Selector類是一個抽象類,不可以直接創建Selector對象。Selector類屬性,在ComboBox、ListBox、TabControl以及ListView中都會用到這些屬性。
4.組合框(ComboBox)
組合框主要由字符框(TextBlock)、撥動按鈕(ToggleButton)和Popup幾個控件組成,如果使用前面我用過的Snoop工具,會發現其中還有其他的一些控件,但其基本功能是由這三個控件組成的。TextBlock用於顯示所選中的條目,ToggleButton給用戶提供按鍵操作,當用戶按下ComboBox右邊的按鈕時,Popup控件顯示ComboBox中的條目內容。
有時需要組合框支持用戶在輸入字符串時自動選擇組合框中的條目的特性,用戶輸入的字符串可以不在組合框的條目中;有時候又需要限制用戶輸入字符串。當需要選擇合適的組合框特性時,要設置IsEditable和IsReadOnly兩個屬性,下圖列出了這兩個屬性的值及其對組合框屬性的影響。
5.TabControl
TabControl在Win32中就有了,不過過去常用在會話框上。它就像一個文件夾,每個文件夾里含有特定的文件,用一個標簽貼在文件夾的側面,然后把文件夾疊起來。這樣,比把文件鋪開在桌面上要省地方,這就是設計TabControl的最初目的。
6.列表框(ListBox)
ListBox中含有至少一個ListBoxItem。ListBoxItem從內容控件(ContentControl)中派生出來,因此具有內容控件的特征。ListBox中有一個SelectionMode屬性,該屬性為枚舉類型。可以取Single、Multiple和Extended三個值,當SelectionMode設為Single時,用戶只能選擇ListBox中一個條目;當SelectionMode設為Multiple時,用戶可以選擇ListBox中多個條目;當SelectionMode設為Extended時,用戶需要按下“SHIFT”鍵,才能選擇ListBox中的多個條目;由於ListBox允許用戶選擇多個ListBoxItem,所以它有一個SelectedItems。這是一個集合,其中含有用戶選擇的多個條目。
7.ListView
ListView也是一個老的控件,它和ListBox非常類似,所以它是ListBox的派生類。ListView和ListBox不同的地方在於,ListView有多列,而且每列都有頭。ListView默認的SelectionMode為Extended。
8.狀態條(StatusBar)
狀態條用於顯示應用程序的當前狀態信息,一般放在窗口的底部。如Office Word主窗口下面的狀態條,Word在其中顯示文檔的當前頁、字數等相關信息。StatusBar是一個條目控件,它是ItemsControl的派生類。
9.樹形控件TreeView和TreeViewItem
TreeView是一個非常重要的控件,微軟在Windows 95中首先引入樹形控件。TreeView用來顯示具有樹形結構的信息,在現實生活中,有很多樹形結構的例子。如家族樹始於某個祖宗,隨着一代代繁衍,家族樹越來越龐大,但沒個家族分支,都可以在樹形圖上找到其來源即“樹根”。中國的家譜就是對家族樹的描述,我們名字中的中間那個字表示輩分(這就是為什么三個字的名字要比兩個字好,兩個字的名字我們無法獲知輩分信息),你可以很容易地從中識別你在家族書中的分支。樹枝分叉的交接處叫做節點,節點有兩個狀態:展開和關閉,一般用兩個不同的圖標來表示這兩種不同的狀態。樹形圖可以直觀地描述節點間的父與子和兄與弟這類關系。
TreeView中的相關屬性
TreeViewItem中的相關屬性
四、文本控件(Text Controls)
文本控件共有4個類,這4個類是:
- 用於用戶輸入口令的PasswordBox;
- 提供基本字符輸入的TextBox;
- 用於增強字符輸入的RichTextBox;
- TextBoxBase是TextBox和RichTextBox的基類,它是一個不能實例化的抽象類
1.口令輸入框(PasswordBox)
為了避免軟件系統不被不相關的人使用,通常需要對用戶進行身份認證,並根據用戶的級別賦予用戶相應的功能。這個過程稱作Authentication和Authorization。
最常用的Authentication方法就是要求用戶輸入用戶名和口令。用戶輸入口令通常不能顯示出來,以防站在用戶邊上的人偷看密碼,所以需要把用戶輸入的字符掩藏起來。過去在MFC中,程序員要對TextBox做一些工作,以滿足上述要求。WPF提供了用於輸入用戶口令的控件——口令輸入框(PasswordBox)。
2.文字輸入框(TextBox)
文字輸入框(TextBox)是一個非常常用的控件,在前面的程序中已經多次用過。TextBox看似簡單,其實它是由多個控件組成的,如果你用Snoop工具檢查TextBox,會看到其中含有Border、ScrollViewer、Grid、Rectangle、TextView、ScrollBar等一些控件。
3.RichTextBox
TextBox中的字符只能有一種格式,若你需要用多種方式顯示字符,或在字符中插入其他的圖像、聲音等對象時,就需要使用RichTextBox。
RichTextBox中的大部分屬性和TextBox相同,都是繼承TextBoxBase中的屬性。RichTextBox中有一個Document屬性,其類型為FlowDocument。正是由於這個屬性,使得RichTextBox中的內容豐富了起來。
五、范圍控件(Range Controls)
ScrollBar、ProgressBar和SlideBar這三個控件統稱為范圍控件,它們都是從同一個基類RangeBase中派生出來的。
RangeBase是一個抽象類,它定義了最大(Maximum),最小(Minimum)值;范圍控件的當前值(Value ),SmallChange和LargeChange兩個屬性則定義了每次變化的單位。范圍控件的取值一定在Minimum和Maximum之間。
1.滾動條(ScrollBar)
滾動條是一個常用的控件,使用起來非常簡單。自己去看屬性參數。
2.滑動條(Slider)
滑動條是一個邊上帶有刻度的范圍控件,在某些情況下使用滑動條很直觀,如多媒體播放器,用戶可以直接通過拉動滑動條上的滑塊來選擇要看的視頻位置。
刻度的位置由TickPlacement屬性確定,其類型為TickPlacement,是一個枚舉類型。它可以取兩個值:TopLeft和BottomRight。當滑動條是水平放置時,若TickPlacement為TopLeft,這是刻度位於滑動條的上方;若TickPlacement為BottomRight時,刻度位於滑動條的下方。當滑動條為垂直放置,TickPlacement控制刻度位於滑動條的左邊或右邊。設定滑動條的刻度有兩種方法,方法之一是設置滑動條的Ticks屬性,這是一個浮點數集合,滑動條會在你設定的浮點數的位置顯示刻度。方法之二是設置TickFrequency,滑動條會在Maximum和Mimimum值之間,根據TickFrequency自動設置相應的刻度。例如,滑動條的最大值為100,最小值為0,TickFrequency為10,那么,活動條刻度的值會自動設為0,10,20,……
當設置IsSelectRangeEnabled為True,並設置SelectionStart和SelectionEnd的值后,滑動條上就會出現選擇范圍的標識。需要注意的是SelectionStart應小於SelectionEnd;並且這兩個值應在Maximum和Minimum之間。
滑動條還可以在鼠標單擊滑塊時,用ToolTip的方式顯示當前滑塊的值。這時要用到AutoToolTipPlacement和AutoToolTipPrecision兩個屬性。
AutoToolTipPrecision用來定義顯示的精度,其值為小數點位數。
3. 進展條(ProgressBar)
當某個任務需要較長時間才能完成時,需要在用戶界面上顯示一個任務進行到什么程度的控件,否則,若什么都不顯示,用戶會認為程序不能運行了。這個控件就是進展條(ProgressBar)。
進展條的默認Minimum值為0,默認Maximum的值為100。使用進展條通常要用到動畫。若不想使用動畫,而又不在乎什么時候任務會結束,可以把IsIndeterminate屬性設為true,直到任務執行完時,再把它設為false。這樣,你會看到進展條中的小矩形一直在動。
注:本文內容整理自《WPF專業編程指南-李應保著》,僅用於筆記學習。