TOC

This article is currently in the process of being translated into Russian (~99% done).

Списочные элементы управления:

The ItemsControl

WPF имеет множество элементов управления для отображения списков данных. Они бывают разного вида, сложности и количества выполняемой для вас работы. Простейший из них это ItemsControl, шаблоны и стили которого нужно писать вручную, часто это именно то что нам надо.

Простой пример ItemsControl

Начнем с простейшего примера, где мы вручную заполним ItemsControl парочкой элементов. Так мы увидим насколько ItemsControl простой:

<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="ItemsControlSample" Height="150" Width="200">
    <Grid Margin="10">
		<ItemsControl>
			<system:String>ItemsControl Item #1</system:String>
			<system:String>ItemsControl Item #2</system:String>
			<system:String>ItemsControl Item #3</system:String>
			<system:String>ItemsControl Item #4</system:String>
			<system:String>ItemsControl Item #5</system:String>
		</ItemsControl>
	</Grid>
</Window>

Можно заметить что здесь нет повторяющихся элементов управления отвечающих за отдельный элемент списка, вместо этого вручную добавлены 5 произвольных элементов TextBlock. Если кликнуть по элементу списка, то ничего не произойдёт, потому что выделение элементов и другие механики попросту отсутствуют.

ItemsControl с привязкой данных

Конечно, не подразумевается, что ItemsControl будет использоваться с элементами, добавленными вручную в разметке, как мы делали это в первом примере. Как и многие другие элементы управления в WPF, ItemsControl сделан для привязки данных (data binding), в которой мы используем шаблон, для того чтобы определить, как наш описанный в коде класс должен быть представлен пользователю.

Для демонстрации я сделал пример, в котором отображается список дел пользователя, а чтобы показать гибкость шаблонов, я использовал ProgressBar для вывода процента завершенности. Сначала код, потом картинка, и затем пояснения:

<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlDataBindingSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ItemsControlDataBindingSample" Height="150" Width="300">
    <Grid Margin="10">
		<ItemsControl Name="icTodoList">
			<ItemsControl.ItemTemplate>
				<DataTemplate>
					<Grid Margin="0,0,0,5">
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="*" />
							<ColumnDefinition Width="100" />
						</Grid.ColumnDefinitions>
						<TextBlock Text="{Binding Title}" />
						<ProgressBar Grid.Column="1" Minimum="0" Maximum="100" Value="{Binding Completion}" />
					</Grid>
				</DataTemplate>
			</ItemsControl.ItemTemplate>
		</ItemsControl>
	</Grid>
</Window>
using System;
using System.Windows;
using System.Collections.Generic;

namespace WpfTutorialSamples.ItemsControl
{
	public partial class ItemsControlDataBindingSample : Window
	{
		public ItemsControlDataBindingSample()
		{
			InitializeComponent();

			List<TodoItem> items = new List<TodoItem>();
			items.Add(new TodoItem() { Title = "Complete this WPF tutorial", Completion = 45 });
			items.Add(new TodoItem() { Title = "Learn C#", Completion = 80 });
			items.Add(new TodoItem() { Title = "Wash the car", Completion = 0 });

			icTodoList.ItemsSource = items;
		}
	}

	public class TodoItem
	{
		public string Title { get; set; }
		public int Completion { get; set; }
	}
}

Главная часть примера - это шаблон, указанный внутри ItemsControl с помощью ItemsControl.ItemTemplate с тэгом DataTemplate внутри. Добавим панель Grid, чтобы получить две колонки: в первой у нас TextBlock, показывающий название задачи, а во второй колонке ProgressBar, значение которого мы привязали к свойству Completion.

Теперь шаблон представляет класс TodoItem, который мы декларировали в коде, там же создали несколько объектов класса и добавили их в список. Затем этот список присвоен свойству ItemsSource нашего ItemsControl, который сделает остальное за нас. Как видим из скриншота, элементы списка отображаются по шаблону.

Свойство ItemsPanelTemplate

В примерах выше, все элементы отображаются сверху вниз и занимают всю ширину. Это происходит потому что ItemsControl по умолчанию помещает все наши элементы в вертикальную StackPanel. Это легко изменить, ведь ItemsControl позволяет указать панель для содержания всех элементов. Например:

<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlPanelSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="ItemsControlPanelSample" Height="150" Width="250">
	<Grid Margin="10">
		<ItemsControl>
			<ItemsControl.ItemsPanel>
				<ItemsPanelTemplate>
					<WrapPanel />
				</ItemsPanelTemplate>
			</ItemsControl.ItemsPanel>
			<ItemsControl.ItemTemplate>
				<DataTemplate>
					<Button Content="{Binding}" Margin="0,0,5,5" />
				</DataTemplate>
			</ItemsControl.ItemTemplate>
			<system:String>Item #1</system:String>
			<system:String>Item #2</system:String>
			<system:String>Item #3</system:String>
			<system:String>Item #4</system:String>
			<system:String>Item #5</system:String>
		</ItemsControl>
	</Grid>
</Window>

С помощью свойства ItemsPanelTemplate мы указали что ItemsControl должен использовать WrapPanel в качестве шаблона, и просто для забавы добавили ItemTemplate меняющий отображение строк так что они выглядят как кнопки. Можно использовать любую панель WPF, но некоторые полезней других.

Еще один хороший пример с панелью UniformGrid, для которой можно указать количество колонок и наши элементы отобразятся в одинаковых по размеру колонках.

<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlPanelSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="ItemsControlPanelSample" Height="150" Width="250">
	<Grid Margin="10">
		<ItemsControl>
			<ItemsControl.ItemsPanel>
				<ItemsPanelTemplate>
					<UniformGrid Columns="2" />
				</ItemsPanelTemplate>
			</ItemsControl.ItemsPanel>
			<ItemsControl.ItemTemplate>
				<DataTemplate>
					<Button Content="{Binding}" Margin="0,0,5,5" />
				</DataTemplate>
			</ItemsControl.ItemTemplate>
			<system:String>Item #1</system:String>
			<system:String>Item #2</system:String>
			<system:String>Item #3</system:String>
			<system:String>Item #4</system:String>
			<system:String>Item #5</system:String>
		</ItemsControl>
	</Grid>
</Window>

ItemsControl с прокруткой

Используя ItemsControl, вы можете столкнуться с обычной проблемой: По умолчанию ItemsControl не имеет бегунков для прокрутки, так что если содержимое не вмещается, оно будет скрыто. Это видно если взять наш первый пример и поменять размер окна:

Это легко решаемо в WPF. Есть несколько возможных решений, например, можно изменить шаблон для ItemsControl, включив в него ScrollViewer, но простейшее решение - это поместить ItemsControl внутрь ScrollViewer. Вот пример:

<Window x:Class="WpfTutorialSamples.ItemsControl.ItemsControlSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="ItemsControlSample" Height="150" Width="200">
	<Grid Margin="10">
		<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
			<ItemsControl>
				<system:String>ItemsControl Item #1</system:String>
				<system:String>ItemsControl Item #2</system:String>
				<system:String>ItemsControl Item #3</system:String>
				<system:String>ItemsControl Item #4</system:String>
				<system:String>ItemsControl Item #5</system:String>
			</ItemsControl>
		</ScrollViewer>
	</Grid>
</Window>

Я установил опции видимости на Auto, так бегунки будут видны по надобности. На картинке видно что теперь есть возможность прокрутки.

Сводка

ItemsControl хорош если требуется полный контроль отображения данных и не требуется возможность выделения элементов. Если всё же нужна возможность выбора, лучше выбрать ListBox или ListView, которые будут описаны в следующих статьях.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!