WPF提供了許多封裝項的集合的控件,本章介紹簡單的ListBox和ComboBox控件,後續哈會介紹更特殊的控件,如ListView、TreeView和ToolBar控件。全部這些控件都繼承自ItemsControl類(ItemsControl類自己又繼承自Control類)。數據庫
ItemsControl類添加了全部基於列表的控件都使用的基本功能。最顯著的是,它提供了填充列表項的兩種方式。最直接的方法是代碼或XAML將列表項直接添加到Items集合中。然而,在WPF中使用數據綁定的方法更廣泛。使用數據綁定方法,需將ItemsSource屬性設置爲但願顯示的具備數據項集合的對象(後續章節介紹與列表數據綁定相關的更多內容)。app
ItemsControl類以後的繼承橙子有些混亂。一個主要分支是選擇器(selector),包括ListBox、ComboBox以及TabControl。這些控件都繼承自Selector類,而且都具備跟蹤當前選擇項(SelectedItem)或其位置(SelectedIndex)的屬性,封裝列表項的控件是另外一個分支,以不一樣方式選擇列表項。該分支包括用於菜單、工具欄以及樹的類——全部這些類都屬於ItemsControl,但不是選擇器。ide
爲了充分發揮全部ItemsControl控件的功能,須要使用數據綁定。即便不從數據庫甚至外部數據源獲取數據,也一樣如此。WPF數據綁定很是廣泛,可以使用各類數據,包括自定義的數據對象和集合。但如今還不須要考慮數據綁定的細節。如今,先快速瀏覽一下ListBox控件和ComboBox控件。工具
1、ListBoxui
ListBox類表明了一種最經常使用的Windows設計——容許用戶從長度可變的列表中選擇一項。編碼
若是將SelectionMode屬性設置爲Multiple或Extended,ListBox類還容許選擇多項。在Multiple模式下,可經過單擊項進行選擇或取消選擇。在Extended模式下,須要按下Ctrl鍵選擇其餘項,或按下Shift鍵選擇某個選項範圍。在這兩種多選模式下,可用SelectedItems集合替代SelectedItem屬性來獲取全部選擇的項。spa
爲向ListBox控件中添加項,可在ListBox元素中嵌套ListBoxItem元素。例如,下面是一個包含顏色列表的ListBox:設計
<ListBox> <ListBoxItem>Yellow</ListBoxItem> <ListBoxItem>Blue</ListBoxItem> <ListBoxItem>Green</ListBoxItem> <ListBoxItem>Red</ListBoxItem> <ListBoxItem>LightBlue</ListBoxItem> <ListBoxItem>Black</ListBoxItem> </ListBox>
不一樣控件採用不一樣方式處理嵌套的內容。ListBox控件在它的Items集合中存儲每一個嵌套的對象。3d
ListBox控件是一個很是靈活的控件。它不只能夠包含ListBoxItem對象,也能夠駐留其餘任意元素。這是由於ListBoxItem類繼承自ContentControl類,從而ListBoxItem可以包含一段嵌套的內容。若是該內容繼承自UIElement類,它將ListBox控件中呈現出來。若是是其餘類型的對象,ListBoxItem對象會調用ToString()方法並顯示最終的文本。code
例如,若是決定建立一個包含圖像的列表,可以使用以下標記:
<ListBox> <ListBoxItem> <Image Source="happyface.jpg"></Image> </ListBoxItem> <ListBoxItem> <Image Source="redx.jpg"></Image> </ListBoxItem> </ListBox>
實際上ListBox控件足夠職能,它能隱式地建立所需的ListBoxItem對象。這意味着可直接在ListBox元素中放置對象。廈門市一個更復雜的示例,該示例使用嵌套的StackPanel對象組合文本和圖像內容:
<Window x:Class="Controls.ImageList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ImageList" Height="300" Width="300"> <ListBox Margin="5" SelectionMode="Multiple" Name="lst" SelectionChanged="lst_SelectionChanged"> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Happy face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="redx.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Warning face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Happy face</Label> </StackPanel> </ListBox> </Window>
在該例中,StackPanel面板變成被ListBoxItem封裝的項。該標記建立的富列表如圖下圖所示:
利用在列表框中的嵌套任意元素的能力,可建立出各類基於列表的控件,而沒必要使用其餘類。例如,Windows窗體的哦該凝聚項中CheckedListBox類,該類顯示在每一個項的旁邊都具備複選框的列表。在WPF中不須要這一特殊類,由於徹底可以使用標準的ListBox控件快速構建相同的效果:
<Window x:Class="Controls.CheckBoxList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="CheckBoxList" Height="300" Width="300"> <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <ListBox Name="lst" SelectionChanged="lst_SelectionChanged" CheckBox.Click="lst_SelectionChanged" > <CheckBox Margin="3">Option 1</CheckBox> <CheckBox Margin="3">Option 2</CheckBox> <CheckBox Margin="3">Option 3</CheckBox> </ListBox> <StackPanel Grid.Row="1" Margin="0,10,0,0"> <TextBlock>Current selection:</TextBlock> <TextBlock Name="txtSelection" TextWrapping="Wrap"></TextBlock> <Button Margin="0,10,0,0" Click="cmd_CheckAllItems">Examine All Items</Button> </StackPanel> </Grid> </Window>
當在列表內部使用不一樣元素時須要注意一點。當讀取SelectedItem值時(以及SelectedItems和Items集合),看不到ListBoxItem對象——反而將看到放入到列表中的對象。在CheckedListBox示例中,這意味着SelectedItem提供了CheckBox對象。
例如,下面是一些響應SelectionChanged事件觸發的代碼。這些代碼獲取當天選中CheckBox對象並顯示該項是否被選中:
private void lst_SelectionChanged(object sender, RoutedEventArgs e) { // Select when checkbox portion is clicked (optional). if (e.OriginalSource is CheckBox) { lst.SelectedItem = e.OriginalSource; } if (lst.SelectedItem == null) return; txtSelection.Text = String.Format( "You chose item at position {0}.\r\nChecked state is {1}.", lst.SelectedIndex, ((CheckBox)lst.SelectedItem).IsChecked); }
在下面的代碼片斷中,相似的代碼遍歷選項集合以肯定哪一項被選中(對於使用複選框的多項選擇列表,能夠編寫相似的代碼來遍歷選中項的集合)。
private void cmd_CheckAllItems(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (CheckBox item in lst.Items) { if (item.IsChecked == true) { sb.Append( item.Content + " is checked."); sb.Append("\r\n"); } } txtSelection.Text = sb.ToString(); }
最終效果以下所示:
在列表框中手動放置項時,由你決定是但願直接插入項仍是在ListBoxItem對象中明確地包含每項。第二種方法一般更清晰,也更繁瑣。最重要的考慮事項是一致性。例如,若是在列表中放置StackPanel對象,ListBox.SelectedItem對象將是StackPanel。若是放置由ListBoxItem對象封裝的StackPanel對象,ListBox.SelectedItem對象將是ListBoxItem,因此可進行響應編碼。
ListBoxItem提供了少量額外功能,經過這些功能可獲得直接嵌套的對象。換言之,ListBoxItem定義了能夠讀取(或設置)的IsSelected屬性,以及用於通知什麼時候選中的Selected和Unselected事件。然而,可以使用ListBox類的成員獲得相似功能,如SelectedItem屬性(或SelectedItems屬性)以及SelectionChanged事件。
有趣的是,當使用嵌套對象方法時,有一項技術可爲特定的對象檢索ListBoxItem封裝器。技巧是使用常被忽視的ContainerFromElement()方法。下面的代碼使用該技術檢查列表中的第一個條目是否被選中:
ListBoxItem item=(ListBoxItem)lst.ContainerFromElement((DependencyObject)lst.SelectedItems[0]); MessageBox.Show("IsSelected:"+item.IsSelected.ToString());
2、ComboBox
ComboBox控件和ListBox控件相似。該控件包含ComboBoxItem對象的集合,既能夠顯示地也能夠隱式地建立該集合。與ListBoxItem相似,ComboBoxItem也是能夠包含任意嵌套元素的內容控件。
ComboBox類和ListBox類之間的重要區別是他們在窗口中呈現自身的方式。Combox控件使用下拉列表,這意味着一次只能選擇一項。
若是但願容許用戶在組合框中經過輸入文本選項一項,就必須將IsEditable屬性設置爲true,而且必須確保選項集合中存儲的是廣泛的純文本的ComboBoxItem對象,或是提供了有意義的ToString()表示的對象。例如,若是使用Image對象填充可編輯的組合框,那麼在上面顯示的文本將只有Image類的全名,這用處不大。
ComboBox控件的侷限之一在於當使用自動改變尺寸功能時該控件改變自身尺寸的方法。ComboBox控件加寬自身以適應它的內容,這意味着當從一項移到另外一項是它會改變自身大小。但沒有簡便的方法告訴ComboBox控件使用包含項的最大尺寸。相反,須要爲Width屬性提供硬編碼的值,而這並不理想。
下面是一個簡單的示例:
<Window x:Class="Controls.ComboBoxTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="ComboBoxTest" Height="300" Width="300"> <StackPanel> <ComboBox Margin="5"> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Happy face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="redx.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Warning face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalAlignment="Center">A Happy face</Label> </StackPanel> </ComboBox> </StackPanel> </Window>
最終效果圖以下所示: