Класс ComboBox представляет выпадающий список. Например, определим элемент ComboBox в xaml:
<Window x:Class="MetanitApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sys="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d" Title="METANIT.COM" Height="200" Width="300"> <StackPanel> <ComboBox> <sys:String>Tom</sys:String> <sys:String>Bob</sys:String> <sys:String>Sam</sys:String> <sys:String>Alice</sys:String> </ComboBox> </StackPanel> </Window>
Здесь в качестве элементов выпадающего списка используются строки. И после запуска программы мы сможем выбрать один из четырех элементов:
В реальности в качестве элементов могут выступать любые объекты, например, элементы TextBlock
:
<ComboBox> <TextBlock>Tom</TextBlock> <TextBlock>Bob</TextBlock> <TextBlock>Sam</TextBlock> <TextBlock>Alice</TextBlock> </ComboBox>
Результат будет тот же самый, что и в предыдущем случае.
Однако также в WPF предоставляет для ComboBoxe специальный тип - ComboBoxItem. ComboBoxItem представляет элемент управления содержимым, в который через свойство Content мы можем поместить другие элементы. Например:
<Window x:Class="MetanitApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="METANIT.COM" Height="200" Width="300"> <StackPanel> <ComboBox> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16">Tom</TextBlock> <TextBlock>Microsoft</TextBlock> </StackPanel> </ComboBoxItem> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16">Bob</TextBlock> <TextBlock>Google</TextBlock> </StackPanel> </ComboBoxItem> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16">Sam</TextBlock> <TextBlock>JetBrains</TextBlock> </StackPanel> </ComboBoxItem> </ComboBox> </StackPanel> </Window>
Стоит отметить, что в примеры выше для демонстрации применяется повторяющаяся разметка. В реальном же приложении для создании подобных разметок, применяются шаблон данных и механизм привязки, которые рассматриваются в последующих главах.
Как и другие элементы управления списками, ComboBox можно отображать объекты пользовательсих классов. Например, определим пустой ComboBox
:
<Window x:Class="MetanitApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="METANIT.COM" Height="200" Width="300"> <StackPanel> <ComboBox x:Name="peopleComboBox" /> </StackPanel> </Window>
В файле связанного кода C# определим класс Person, который представляет данные, и добавим в список несколько объектов этого класса:
using System.Windows; namespace MetanitApp; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); peopleComboBox.ItemsSource = new Person[] { new Person { Name = "Tom", Company = "Microsoft" }, new Person { Name = "Bob", Company = "Google" }, new Person { Name = "Sam", Company = "JetBrains" } }; } } public class Person { public string Name { get; set; } = ""; public string Company { get; set; } = ""; public override string ToString() => $"{Name} ({Company})"; }
По умолчанию ComboBox выводит строковое представление объекта. Если необходимо отображать значение определенного свойства, применяется свойство DisplayMemberPath
,
например, выведем значение свойства Name:
<ComboBox x:Name="peopleComboBox" DisplayMemberPath="Name" />
Обрабатывая событие SelectionChanged, мы можем динамически получать выделенный элемент. Для управления выбранными объектами класс ComboBox предоставляет следующие свойства:
SelectedItem: выбранный объект списка
SelectedValue: выбранное значение
SelectedIndex: индекс выбранного объекта в списке
Определим в xaml следующий интерфейс:
<Window x:Class="MetanitApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="METANIT.COM" Height="200" Width="300"> <StackPanel> <TextBlock x:Name="selectedLabel" FontSize="18" /> <ComboBox x:Name="peopleComboBox" SelectionChanged="peopleComboBox_SelectionChanged" /> </StackPanel> </Window>
Здесь для события SelectionChanged
установлен обработчик "peopleComboBox_SelectionChanged", а для вывода выбранного объекта определен элемент TextBlock.
В коде C# определим обработчик события:
using System.Windows; using System.Windows.Controls; namespace MetanitApp; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); peopleComboBox.ItemsSource = new Person[] { new Person { Name = "Tom", Company = "Microsoft" }, new Person { Name = "Bob", Company = "Google" }, new Person { Name = "Sam", Company = "JetBrains" } }; peopleComboBox.SelectedIndex = 1; // по умолчанию будет выбран второй элемент } private void peopleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if(peopleComboBox.SelectedItem is Person person) { selectedLabel.Text = person.Name; } } } public class Person { public string Name { get; set; } = ""; public string Company { get; set; } = ""; public override string ToString() => $"{Name} ({Company})"; }
Поскольку здесь элементами списка являются объекты Person, то выбранный объект мы можем привести к типу Person
if(peopleComboBox.SelectedItem is Person person)
И вывести в текстовую метку значение свойства Name:
Также мы могли бы использовать свойство SelectedValue, которое представляет выбранное значение. Для его использования определим следующий код xaml:
<Window x:Class="MetanitApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="METANIT.COM" Height="200" Width="300"> <StackPanel> <TextBlock x:Name="selectedPerson" FontSize="18" /> <ComboBox x:Name="peopleComboBox" SelectedValuePath="Name" SelectionChanged="peopleComboBox_SelectionChanged" /> </StackPanel> </Window>
Обратите внимание на свойство SelectedValuePath="Name"
- здесь мы указываем, что свойство "Name" будет выступать в качестве свойства значения.
Для обработки события выбора элемента определим следующий код C#:
using System.Windows; using System.Windows.Controls; namespace MetanitApp; public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); peopleComboBox.ItemsSource = new Person[] { new Person { Name = "Tom", Company = "Microsoft" }, new Person { Name = "Bob", Company = "Google" }, new Person { Name = "Sam", Company = "JetBrains" } }; peopleComboBox.SelectedIndex = 1; // по умолчанию будет выбран второй элемент } private void peopleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if(peopleComboBox.SelectedValue is { }) // если не равно null { selectedPerson.Text = peopleComboBox.SelectedValue.ToString(); } // или так // selectedPerson.Text = peopleComboBox.SelectedValue?.ToString(); } } public class Person { public string Name { get; set; } = ""; public string Company { get; set; } = ""; public override string ToString() => $"{Name} ({Company})"; }
Здесь проверяем, не равно ли peopleComboBox.SelectedValue
null (хотя в примере выше это не имеет смысла, поскольку это свойство представляет строку), и
выводим значение этого свойства в текстовый блок. Результат будет аналогичен предыдущему.
Установка свойства IsEditable="True"
позволяет вводить в поле списка начальные символы, а затем функция автозаполнения подставит
подходящий результат. По умолчанию свойство имеет значение False
.
Это свойство работает в комбинации со свойством IsReadOnly
: оно указывает, является поле ввода доступным только для чтения.
По умолчанию имеет значение False
, поэтому если IsEditable="True"
, то мы можем вводить туда произвольный текст.
Еще одно свойство StaysOpenOnEdit
при установке в True
позволяет сделать список раскрытым на время ввода значений в поле ввода.