【WPF】-ComboBox控件详解

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/1504809782536540160

Demo下载:

可编辑

在第一个示例中,用户只能从我们的项目列表中进行选择,但是 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属性以了解用户输入或选择的值。

 

posted @ 2024-03-09 21:02  VisionCode  阅读(677)  评论(0编辑  收藏  举报