ItemTemplate и DataTemplate

Последнее обновление: 26.02.2016

Все элементы управления списками имеют свойство ItemTemplate, которое позволяет задать свой шаблон отображения данных. В качестве значения оно принимает объект DataTemplate. В качестве самих данных, которые отображаются в DataTemplate, как правило, выступают объекты пользовательских классов, создаваемых самим разработчиком. Сам шаблон данных представляет разметку xaml, которая управляет визуализацией элемента.

Итак, добавим в проект следующий класс Phone, который будет представлять модель телефона:

public class Phone
{
    public int Id { get; set; }
    public string Title { get; set; } // модель телефона
    public string Company { get; set; } // производитель
    public string ImagePath { get; set; } // путь к изображению
}

В коде xaml определим шаблон данных для списка смартфонов:

<Window x:Class="DataApp.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:DataApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Grid>
        <ListBox x:Name="phonesList" SelectionChanged="phonesList_SelectionChanged">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Margin="5">
                        <Image Width="100" Height="75" Source="{Binding Path=ImagePath}" />
                        <TextBlock FontSize="16" Text="{Binding Path=Title}" HorizontalAlignment="Center" />
                        <TextBlock FontSize="16" Text="{Binding Path=Company}" HorizontalAlignment="Center" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

Итак, здесь шаблон данных представлен следующей разметкой:

<DataTemplate>
    <StackPanel Margin="5">
        <Image Width="100" Height="75" Source="{Binding Path=ImagePath}" />
        <TextBlock FontSize="16" Text="{Binding Path=Title}" HorizontalAlignment="Center" />
        <TextBlock FontSize="16" Text="{Binding Path=Company}" HorizontalAlignment="Center" />
    </StackPanel>
</DataTemplate>

Для каждого элемента применяется привязка к определенному свойству объекта Phone. То есть фактически в визуальном плане каждый элемент будет представлять собой StackPanel с набором элементов Image и TextBlock.

Далее создадим в коде C# коллекцию смартфонов и установим ее в качестве источника данных:

public partial class MainWindow : Window
{
    public ObservableCollection<Phone> Phones { get; set; }
    public MainWindow()
    {
        InitializeComponent();

        Phones = new ObservableCollection<Phone>
        {
            new Phone {Id=1, ImagePath="/Images/iphone6s.jpg", Title="iPhone 6S", Company="Apple" },
            new Phone {Id=2, ImagePath="/Images/lumia950.jpg", Title="Lumia 950", Company="Microsoft" },
            new Phone {Id=3, ImagePath="/Images/nexus5x.jpg", Title="Nexus 5X", Company="Google" },
            new Phone {Id=4, ImagePath="/Images/galaxys6.jpg", Title="Galaxy S6", Company="Samsung"}
        };
        phonesList.ItemsSource = Phones;
    } 
	
	private void phonesList_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        Phone p = (Phone)phonesList.SelectedItem;
        MessageBox.Show(p.Title);
    }
}

Здесь создается 4 объекта Phone. Для каждого объекта устанавливаются необходимые значения. Причем свойство ImagePath указывает на путь к изображению в папке Images. Предполагается, что в проект добавлена папка Images, в которой есть четыре изображения для каждой из моделей.

И также здесь определяется обработчик выбора элемента в списке. Несмотря на то, что список представляет сложные данные, мы все равно сможем обработать выбор пользователя и получить выбранный объект. И так как DataTemplate отображает объекты Phone, то выделенный элемент мы можем привести к типу Phone.

В итоге получится следующее приложение:

DataTemplate в WPF

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

<Window x:Class="DataApp.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:DataApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="listTemplate">
            <StackPanel Margin="5">
                <Image Width="100" Height="75" Source="{Binding Path=ImagePath}" />
                <TextBlock FontSize="16" Text="{Binding Path=Title}" HorizontalAlignment="Center" />
                <TextBlock FontSize="16" Text="{Binding Path=Company}" HorizontalAlignment="Center" />
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox x:Name="phonesList" ItemTemplate="{StaticResource listTemplate}" 
			 SelectionChanged="phonesList_SelectionChanged"  />
    </Grid>
</Window>

Триггеры данных

С помощью триггеров данных (data triggers) можно задать дополнительную логику визуализации, которая срабатывает, если свойство привязанного объекта принимает то или иное значение. Например, в случае с примером выше, допустим, мы хотим, если у отображаемого телефона свойство Company равно Microsoft, то этот элемент выделяется жирным или выделяется красным цветом. И для этого добавим в шаблон данных DataTemplate триггер данных:

<Window x:Class="DataApp.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:DataApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">
    <Window.Resources>
        <DataTemplate x:Key="listTemplate">
            <StackPanel Margin="5">
                <Border x:Name="phoneImageBorder">
                    <Image Width="100" Name="phoneImage" Height="75" Source="{Binding Path=ImagePath}" />
                </Border>
                <TextBlock FontSize="16" Name="phoneTitle" Text="{Binding Path=Title}" HorizontalAlignment="Center" />
                <TextBlock FontSize="16" Text="{Binding Path=Company}" HorizontalAlignment="Center" />
            </StackPanel>
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Company}" Value="Microsoft">
                    <Setter TargetName="phoneTitle" Property="FontWeight" Value="Bold" />
                    <Setter TargetName="phoneImageBorder" Property="BorderBrush" Value="Red" />
                    <Setter TargetName="phoneImageBorder" Property="BorderThickness" Value="3" />
                </DataTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox x:Name="phonesList" ItemTemplate="{StaticResource listTemplate}"
             SelectionChanged="phonesList_SelectionChanged"  />
    </Grid>
</Window>

Для визуализации изображение помещено в элемент Border, который имеет имя "phoneImageBorder". С помощью триггера данных у этого элемента изменяется ширин и цвет границы. Кроме того, меняется жирность шрифта, который выводит название модели:

<DataTrigger Binding="{Binding Company}" Value="Microsoft">
    <Setter TargetName="phoneTitle" Property="FontWeight" Value="Bold" />
    <Setter TargetName="phoneImageBorder" Property="BorderBrush" Value="Red" />
    <Setter TargetName="phoneImageBorder" Property="BorderThickness" Value="3" />
</DataTrigger>

В итоге мы получим следующий визуальный эффект:

DataTrigger в DataTemplate
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850