ComboBox 控制元件在很多方面都類似於 ListBox 控制元件,但佔用的空間要少得多,因為專案列表在不需要時會隱藏起來。ComboBox 控制元件在 Windows 中的很多地方都有使用,但為了確保每個人都知道它的外觀和工作方式,我們將直接進入一個簡單的示例:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox>
<ComboBoxItem>ComboBox Item #1</ComboBoxItem>
<ComboBoxItem IsSelected="True">ComboBox Item #2</ComboBoxItem>
<ComboBoxItem>ComboBox Item #3</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
在螢幕截圖中,我透過單擊來啟用控制元件,從而顯示專案列表。從程式碼中可以看出,ComboBox 的簡單形式非常易於使用。我在這裡所做的只是手動新增一些專案,透過在其上設定 IsSelected 屬性使其中一個成為預設選定專案。
自定義內容
在第一個示例中,我們只在專案中顯示文字,這對於 ComboBox 控制元件來說很常見,但是由於 ComboBoxItem 是一個 ContentControl,我們實際上可以使用幾乎任何內容作為內容。讓我們嘗試製作一個稍微複雜的專案列表:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxCustomContentSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxCustomContentSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_red.png" />
<TextBlock Foreground="Red">Red</TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_green.png" />
<TextBlock Foreground="Green">Green</TextBlock>
</StackPanel>
</ComboBoxItem>
<ComboBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfTutorialSamples;component/Images/bullet_blue.png" />
<TextBlock Foreground="Blue">Blue</TextBlock>
</StackPanel>
</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
對於每個 ComboBoxItem,我們現在新增一個 StackPanel,在其中新增一個 Image 和一個 TextBlock。這使我們可以完全控制內容和文字渲染,正如您從螢幕截圖中看到的那樣,其中文字顏色和影像都表示顏色值。
繫結 ComboBox 的資料
正如您從第一個示例中看到的那樣,使用 XAML 手動定義 ComboBox 控制元件的專案很容易,但您可能很快就會遇到需要專案來自某種資料來源(如資料庫或只是記憶體列表。使用 WPF 資料繫結和自定義模板,我們可以輕鬆呈現顏色列表,包括顏色預覽:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxDataBindingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxDataBindingSample" Height="200" Width="200">
<StackPanel Margin="10">
<ComboBox Name="cmbColors">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
namespace WpfTutorialSamples.ComboBox_control
{
public partial class ComboBoxDataBindingSample : Window
{
public ComboBoxDataBindingSample()
{
InitializeComponent();
cmbColors.ItemsSource = typeof(Colors).GetProperties();
}
}
}
它實際上很簡單:在程式碼隱藏中,我使用基於反射的方法和 Colors 類獲取所有顏色的列表。我將它分配給ComboBox的ItemsSource屬性,然後它使用我在 XAML 部分中定義的模板呈現每種顏色。
每個專案,由 ItemTemplate 定義,由一個 StackPanel 和一個 Rectangle 和一個 TextBlock 組成,每個都繫結到顏色值。這為我們提供了一個完整的顏色列表,只需最少的努力 - 它看起來也很不錯,對吧?
推薦一款WPF MVVM框架開源專案:Newbeecoder.UI
https://www.zhihu.com/video/1504809782536540160Demo下載:
可編輯
在第一個示例中,使用者只能從我們的專案列表中進行選擇,但是 ComboBox 的一個很酷的地方是它支援讓使用者從專案列表中進行選擇或輸入自己的值的可能性。這在您希望透過為使用者提供一組預定義的選項來幫助他們,同時仍然為他們提供手動輸入所需值的選項的情況下非常有用。這一切都由IsEditable屬性控制 ,它改變了 ComboBox 的行為和外觀:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxEditableSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxEditableSample" Height="150" Width="200">
<StackPanel Margin="10">
<ComboBox IsEditable="True">
<ComboBoxItem>ComboBox Item #1</ComboBoxItem>
<ComboBoxItem>ComboBox Item #2</ComboBoxItem>
<ComboBoxItem>ComboBox Item #3</ComboBoxItem>
</ComboBox>
</StackPanel>
</Window>
如您所見,我可以輸入一個完全不同的值或從列表中選擇一個。如果從列表中選擇,它只會覆蓋 ComboBox 的文字。
作為一個可愛的小獎勵,當使用者開始輸入時,ComboBox 將自動嘗試幫助使用者選擇現有值,正如您從下一個螢幕截圖中看到的,我剛剛開始輸入“Co”:
預設情況下,匹配不區分大小寫,但您可以透過將IsTextSearchCaseSensitive設定為 True 來實現。如果您根本不想要這種自動完成行為,您可以透過將IsTextSearchEnabled設定為 False來禁用它。
使用組合框選擇
使用 ComboBox 控制元件的一個關鍵部分是能夠讀取使用者選擇,甚至可以用程式碼對其進行控制。在下一個示例中,我重新使用了資料繫結 ComboBox 示例,但新增了一些用於控制選擇的按鈕。我還使用SelectionChanged事件來捕獲所選專案的更改時間,無論是由程式碼還是由使用者,並對其採取行動。
這是示例:
<Window x:Class="WpfTutorialSamples.ComboBox_control.ComboBoxSelectionSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ComboBoxSelectionSample" Height="125" Width="250">
<StackPanel Margin="10">
<ComboBox Name="cmbColors" SelectionChanged="cmbColors_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<WrapPanel Margin="15" HorizontalAlignment="Center">
<Button Name="btnPrevious" Click="btnPrevious_Click" Width="55">Previous</Button>
<Button Name="btnNext" Click="btnNext_Click" Margin="5,0" Width="55">Next</Button>
<Button Name="btnBlue" Click="btnBlue_Click" Width="55">Blue</Button>
</WrapPanel>
</StackPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Media;
namespace WpfTutorialSamples.ComboBox_control
{
public partial class ComboBoxSelectionSample : Window
{
public ComboBoxSelectionSample()
{
InitializeComponent();
cmbColors.ItemsSource = typeof(Colors).GetProperties();
}
private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
if(cmbColors.SelectedIndex > 0)
cmbColors.SelectedIndex = cmbColors.SelectedIndex - 1;
}
private void btnNext_Click(object sender, RoutedEventArgs e)
{
if(cmbColors.SelectedIndex < cmbColors.Items.Count-1)
cmbColors.SelectedIndex = cmbColors.SelectedIndex + 1;
}
private void btnBlue_Click(object sender, RoutedEventArgs e)
{
cmbColors.SelectedItem = typeof(Colors).GetProperty("Blue");
}
private void cmbColors_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
Color selectedColor = (Color)(cmbColors.SelectedItem as PropertyInfo).GetValue(null, null);
this.Background = new SolidColorBrush(selectedColor);
}
}
}
這個例子有趣的部分是我們三個按鈕的三個事件處理程式,以及SelectionChanged事件處理程式。在前兩項中,我們透過讀取SelectedIndex屬性然後對其進行減法或加法來選擇上一項或下一項。非常簡單且易於使用。
在第三個事件處理程式中,我們使用 SelectedItem 根據值選擇特定專案。我在這裡做了一些額外的工作(使用 .NET 反射),因為 ComboBox 繫結到一個屬性列表,每個屬性都是一個顏色,而不是一個簡單的顏色列表,但基本上都是關於給出一個包含的值SelectedItem屬性的專案。
在第四個也是最後一個事件處理程式中,我響應正在更改的所選專案。發生這種情況時,我讀取選定的顏色(再次使用反射,如上所述),然後使用選定的顏色為視窗建立新的背景畫筆。效果可以在截圖上看到。
如果您正在使用可編輯的 ComboBox(IsEditable 屬性設定為 true),您可以讀取Text屬性以瞭解使用者輸入或選擇的值。