WPF提供了許多封裝項的集合的控制元件,本章介紹簡單的ListBox和ComboBox控制元件,后續哈會介紹更特殊的控制元件,如ListView、TreeView和ToolBar控制元件,所有這些控制元件都繼承自ItemsControl類(ItemsControl類本身又繼承自Control類),
ItemsControl類添加了所有基于串列的控制元件都使用的基本功能,最顯著的是,它提供了填充串列項的兩種方式,最直接的方法是代碼或XAML將串列項直接添加到Items集合中,然而,在WPF中使用資料系結的方法更普遍,使用資料系結方法,需將ItemsSource屬性設定為希望顯示的具有資料項集合的物件(后續章節介紹與串列資料系結相關的更多內容),
ItemsControl類之后的繼承橙子有些混亂,一個主要分支是選擇器(selector),包括ListBox、ComboBox以及TabControl,這些控制元件都繼承自Selector類,并且都具有跟蹤當前選擇項(SelectedItem)或其位置(SelectedIndex)的屬性,封裝串列項的控制元件是另一個分支,以不同方式選擇串列項,該分支包括用于選單、工具列以及樹的類——所有這些類都屬于ItemsControl,但不是選擇器,
為了充分發揮所有ItemsControl控制元件的功能,需要使用資料系結,即使不從資料庫甚至外部資料源獲取資料,也同樣如此,WPF資料系結非常普遍,可使用各種資料,包括自定義的資料物件和集合,但現在還不需要考慮資料系結的細節,現在,先快速瀏覽一下ListBox控制元件和ComboBox控制元件,
一、ListBox
ListBox類代表了一種最常用的Windows設計——允許用戶從長度可變的串列中選擇一項,
如果將SelectionMode屬性設定為Multiple或Extended,ListBox類還允許選擇多項,在Multiple模式下,可通過單擊項進行選擇或取消選擇,在Extended模式下,需要按下Ctrl鍵選擇其他項,或按下Shift鍵選擇某個選項范圍,在這兩種多選模式下,可用SelectedItems集合替代SelectedItem屬性來獲取所有選擇的項,
為向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集合中存盤每個嵌套的物件,
ListBox控制元件是一個非常靈活的控制元件,它不僅可以包含ListBoxItem物件,也可以駐留其他任意元素,這是因為ListBoxItem類繼承自ContentControl類,從而ListBoxItem能夠包含一段嵌套的內容,如果該內容繼承自UIElement類,它將ListBox控制元件中呈現出來,如果是其他型別的物件,ListBoxItem物件會呼叫ToString()方法并顯示最終的文本,
例如,如果決定創建一個包含影像的串列,可使用如下標記:
<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>ImageListBox
在該例中,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>CheckBoxList
當在串列內部使用不同元素時需要注意一點,當讀取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());
二、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>ComboBoxTest
最終效果圖如下所示:


轉載請註明出處,本文鏈接:https://www.uj5u.com/net/5927.html
標籤:WPF
