Содержание
Списки элементов в WPF и, в принципе, в приложениях используются довольно часто. Такие элементы управления обычно содержат два и более однотипных объекта, которые пользователь может выбрать. В WPF существует ряд элементов управления, позволяющих хранить списки элементов и основные из них — это ListBox
, ComboBox
, ListView
и TreeView
. В этой части мы рассмотрим два из этих компонентов — ListBox
и ComboBox
Списки элементов: иерархия классов
Вначале рассмотрим иерархию классов, реализующих элементы управления списками в WPF, чтобы в дальнейшем можно было систематизировать информацию по работе таких элементов:
Элемент ItemsControl
Все элементы управления списками в WPF имею одного общего предка — класс ItemsControl
, который представляет собой элемент управления для хранения и работы со коллекциями других элементов. В частности, этот класс предоставляет нам следующие свойства для работы с коллекциями элементов:
Свойство | Тип | Описание |
Items |
ItemCollection |
Коллекция, используемая для создания содержимого ItemsControl (только для чтения) |
ItemsSource |
IEnumerable |
Коллекция, используемая для создания содержимого ItemsControl (свойство доступно для чтения и записи) |
В свою очередь, свойство ItemCollection
предоставляет нам следующие методы для управления коллекцией элементов:
Метод | Описание |
public int Add(object newItem); |
Добавляет новый элемент в список и возвращает индекс добавленного элемента в коллекции |
public void Clear(); |
Удаляет все элементы из коллекции |
public override bool Contains(object containItem); |
Проверяет наличие элемента containItem в коллекции |
public void Insert(int insertIndex, object insertItem); |
Вставляет элемент insertItem в позицию insertIndex |
public void Remove(object removeItem); |
Удаляет элемент removeItem из коллекции |
public void RemoveAt(int removeIndex); |
Удаляет из коллекции элемент с индексом removeIndex |
Компонент Selector
Класс Selector
наследуется от ItemsControl
и предоставляет элемент управления, позволяющий пользователю выбрать один из его дочерних элементов. Этот класс дополняет работу со списками элементов следующими свойствами:
Свойство | Тип | Описание |
SelectedIndex |
int |
Индекс выбранного пользователем элемента в списке |
SelectedItem |
object |
Выбранный пользователем элемент |
SelectedValue |
object |
Значение SelectedItem , получаемое через SelectedValuePath . |
SelectedValuePath |
string |
Путь для получения SelectedItem или SelectedValue |
Также, этот элемент предоставляет нам событие:
Событие | Описание |
public event SelectionChangedEventHandler SelectionChanged; |
Генерируется при изменении выбора элемента в списке |
Таким образом, элементы управления ListBox
и ComboBox
в WPF получаю все свойства и события своих предком — классов ItemsControl
и Selector
, позволяя манипулировать списком элементов. Теперь рассмотрим непосредственно эти элементы управления.
Списки элементов: ListBox
Элемент управления ListBox
представляет собой простой список выбора, при этом, пользователь может выбрать как один, так и несколько элементов. Класс ListBox предоставляет нам для работы следующие свойства:
Свойство | Тип | Описание |
SelectedItems |
IList |
Список выбранных элементов |
SelectionMode |
SelectionMode |
Режим выбора элементов в списке. Может принимать следующие значения:
|
Заполнение ListBox в WPF строками
Рассмотрим работу с ListBox
на следующем примере:
<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" xmlns:sys="clr-namespace:System;assembly=mscorlib"> <Grid> <ListBox x:Name="list" SelectionMode="Single" SelectionChanged="ListBox_SelectionChanged"> <sys:String>Первый</sys:String> <sys:String>Второй</sys:String> <sys:String>Третий</sys:String> <sys:String>Четвертый</sys:String> </ListBox> </Grid> </Window>
В качестве элементов ListBox
мы используем обычные строки, для чего подключаем пространство имен:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Режим выбора элементов мы устанавливаем как Single
, чтобы можно было за раз выбрать только один элемент списка и определяем обработчик события SelectionChanged
, который выглядит следующим образом:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (list.SelectedItem != null) MessageBox.Show(list.SelectedItem.ToString()); }
Запустим приложение и попробуем выбрать какой-нибудь элемент списка:
Использование ListBoxItem в WPF для заполнения ListBox
Ещё один вариант формирования списка ListBox
непосредственно в разметке XAML заключается в использовании специального элемента ListBoxItem
, например, так:
<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <ListBox x:Name="list" SelectionMode="Extended" SelectionChanged="ListBox_SelectionChanged"> <ListBoxItem>Первый</ListBoxItem> <ListBoxItem>Второй</ListBoxItem> <ListBoxItem>Третий</ListBoxItem> <ListBoxItem>Четвертый</ListBoxItem> </ListBox> </Grid> </Window>
Этот способ избавляет нас от необходимости подключения дополнительного пространства имен, а также расширяет возможности работы с элементами списка, например, задать свойства фона, цвета текста элемента или сразу установить выбранный элемент списка:
<ListBox x:Name="list" SelectionMode="Extended" SelectionChanged="ListBox_SelectionChanged"> <ListBoxItem Background="LightGreen" IsSelected="True">Первый</ListBoxItem> <ListBoxItem Background="LightBlue" Foreground="Blue">Второй</ListBoxItem> <ListBoxItem Background="LightPink" Foreground="Red">Третий</ListBoxItem> <ListBoxItem>Четвертый</ListBoxItem> </ListBox>
При этом, каждый элемент списка представляет собой ListBoxItem
, то есть, для доступа к содержимому элемента мы должны немного переписать обработчик события SelectionChanged
следующим образом:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (list.SelectedItem != null) { if ((list.SelectedItem is ListBoxItem data) && (data.Content != null)) MessageBox.Show(data.Content.ToString()); } }
Теперь при запуске приложения будет сразу выбран первый элемент списка.
Программное заполнение ListBox в WPF
Для заполнения списка элементов ListBox
мы можем воспользоваться свойством Items
. Изменим разметку XAML следующим образом:
<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <StackPanel> <ListBox x:Name="list" SelectionMode="Extended" SelectionChanged="ListBox_SelectionChanged"> <ListBoxItem Background="LightGreen">Смартфоны</ListBoxItem> <ListBoxItem Background="LightBlue" Foreground="Blue">Программное обеспечение</ListBoxItem> <ListBoxItem Background="LightPink" Foreground="Red">Языки программирования</ListBoxItem> </ListBox> <ListBox x:Name="elements"></ListBox> </StackPanel> </Window>
Здесь мы добавили новый список ListBox
с именем elements
:
<ListBox x:Name="elements"></ListBox>
Теперь перепишем обработчик SelectionChanged
первого списка следующим образом:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (list.SelectedItem != null) { if ((list.SelectedItem is ListBoxItem data) && (data.Content != null)) { elements.Items.Clear(); switch (data.Content.ToString()) { case "Смартфоны": { elements.Items.Add("iPhone"); elements.Items.Add("Xiomi"); elements.Items.Add("Samsung"); break; } case "Программное обеспечение": { elements.Items.Add("Visual Studio"); elements.Items.Add("Microsoft Windows"); elements.Items.Add("Microsoft Office"); break; } case "Языки программирования": { elements.Items.Add("C#"); elements.Items.Add("Basic"); elements.Items.Add("Python"); break; } } } } }
При выборе элемента в первом списке все элементы во втором списке удаляются:
elements.Items.Clear();
а, затем, в зависимости от выбранного значения, заполняется новыми элементами. Вот как будет выглядеть результат работы приложения:
Отображение сложных объектов в ListBox
Часто нам необходимо отобразить в списке ListBox
данные какого-либо сложного объекта, например, рассмотрим заполнение ListBox
объектами следующего типа:
public class Element { public int Id { get; set; } public string? Name { get; set; } }
Для того, чтобы заполнить ListBox
такими элементами, нам необходимо воспользоваться свойством ItemSource
. Например, перепишем работу с нашими списками следующим образом:
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (list.SelectedItem != null) { if ((list.SelectedItem is ListBoxItem data) && (data.Content != null)) { switch (data.Content.ToString()) { case "Смартфоны": { elements.ItemsSource = new List<Element>() { new Element(){ Id=1, Name = "iPhone"}, new Element(){ Id=2, Name = "Xiomi"}, new Element(){ Id=3, Name = "Samsung"}, }; break; } case "Программное обеспечение": { elements.ItemsSource = new List<Element>() { new Element(){ Id=1, Name = "Visual Studio"}, new Element(){ Id=2, Name = "Microsoft Windows"}, new Element(){ Id=3, Name = "Microsoft Office"}, }; break; } case "Языки программирования": { elements.ItemsSource = new List<Element>() { new Element(){ Id=1, Name = "C#"}, new Element(){ Id=2, Name = "Basic"}, new Element(){ Id=3, Name = "Python"}, }; break; } } elements.DisplayMemberPath = "Name"; } } }
Обратите внимание, что при использовании свойства ItemSource
нам становится недоступно свойство Items
. Свойству ItemSource
мы сразу назначаем список элементов:
elements.ItemsSource = new List<Element>() { new Element(){ Id=1, Name = "iPhone"}, new Element(){ Id=2, Name = "Xiomi"}, new Element(){ Id=3, Name = "Samsung"}, };
Для того, чтобы указать значение какого свойства объекта необходимо отображать в списке, мы указываем значение свойства DisplayMemberPath
:
elements.DisplayMemberPath = "Name";
Таким образом, в свойстве SelectedItem
теперь будет содержаться объект типа Element
, а отображаться в списке будет значение свойства Name
.
Списки элементов: ComboBox
Элемент управления ComboBox
представляет собой раскрывающийся список элементов. Способы создания таких списков аналогичны способам рассмотренным выше для ListBox
, поэтому не будем повторяться, а сразу рассмотрим свойства ComboBox
и немного поэкспериментируем с его оформлением. Итак, ComboBox
предоставляет нам следующие свойства:
Свойство | Тип | Описание |
IsDropDownOpen |
bool |
Указывает раскрыт ли список выбора в данный момент |
IsEditable |
bool |
Указывает доступно ли редактирование текста в поле ComboBox |
IsReadOnly |
bool |
Определяет доступ только для чтения |
StaysOpenOnEdit |
bool |
Определяет будет ли раскрыт список выбора, когда пользователь щелкает по текстовому полю ComboBox |
Text |
string |
Текст в поле ComboBox |
Создадим следующий элемент управления ComboBox
:
<ComboBox StaysOpenOnEdit="True" IsEditable="True" IsReadOnly="False"> <ComboBoxItem>Телефоны</ComboBoxItem> <ComboBoxItem>Ноутбуки</ComboBoxItem> <ComboBoxItem>Бытовая техника</ComboBoxItem> </ComboBox>
Здесь мы для заполнения списка воспользовались элементами ComboBoxItem
и допускаем возможность ручного ввода значений в поле ComboBox
. В запущенном приложении наш список выбора будет работать следующим образом:
Так как ComboBoxItem
может иметь любое содержимое, то ничто нам не мешает расположить в нем и другие элементы управления WPF, например:
<StackPanel> <ComboBox StaysOpenOnEdit="True" IsEditable="False" IsReadOnly="True"> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16" FontWeight="Bold">Телефоны</TextBlock> <TextBlock FontSize="10" Foreground="Gray">Список моделей телефонов</TextBlock> </StackPanel> </ComboBoxItem> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16" FontWeight="Bold">Ноутбуки</TextBlock> <TextBlock FontSize="10" Foreground="Gray">Список моделей ноутбуков</TextBlock> </StackPanel> </ComboBoxItem> <ComboBoxItem> <StackPanel> <TextBlock FontSize="16" FontWeight="Bold">Бытовая техника</TextBlock> <TextBlock FontSize="10" Foreground="Gray">Телевизоры, холодильники, стиральные машины</TextBlock> </StackPanel> </ComboBoxItem> </ComboBox> </StackPanel>
Теперь наш список выбора будет выглядеть следующим образом:
Итого
Списки элементов ListBox
и ComboBox
представляют собой элементы управления WPF, позволяющие хранить и выбирать один или несколько дочерних элементов. Для заполнения ListBox
и ComboBox
мы можем использовать как обычные строки, так и специальные элементы ListBoxItem
и ComboBoxItem
, которые позволяют размещать в элементах списка произвольные объекты и настраивать их внешний вид.