Visão geral de modelagem dos dadosData Templating Overview

O modelo de modelagem de dados do WPF fornece grande flexibilidade para definir a apresentação dos dados.The WPF data templating model provides you with great flexibility to define the presentation of your data. Os controles do WPF têm uma funcionalidade interna para dar suporte à personalização da apresentação de dados.WPF controls have built-in functionality to support the customization of data presentation. Este tópico primeiro demonstra como definir um DataTemplate e, em seguida, apresenta outros recursos de modelagem de dados, como a seleção de modelos com base na lógica personalizada e o suporte para a exibição de dados hierárquicos.This topic first demonstrates how to define a DataTemplate and then introduces other data templating features, such as the selection of templates based on custom logic and the support for the display of hierarchical data.

PrerequisitesPrerequisites

Este tópico se concentra nos recursos de modelagem de dados e não é uma introdução dos conceitos de associação de dados.This topic focuses on data templating features and is not an introduction of data binding concepts. Para obter informações sobre conceitos de associação de dados, consulte Visão geral de associação de dados.For information about basic data binding concepts, see the Data Binding Overview.

DataTemplate é sobre a apresentação de dados e é um dos muitos recursos fornecidos pelo modelo de modelagem e estilo do WPF.DataTemplate is about the presentation of data and is one of the many features provided by the WPF styling and templating model. Para obter uma introdução do modelo de modelagem e estilo do WPF, como usar um Style para definir propriedades em controles, consulte o tópico estilo e modelagem .For an introduction of the WPF styling and templating model, such as how to use a Style to set properties on controls, see the Styling and Templating topic.

Além disso, é importante entender Resources, que são essencialmente o que permite que objetos como Style e DataTemplate sejam reutilizáveis.In addition, it is important to understand Resources, which are essentially what enable objects such as Style and DataTemplate to be reusable. Para obter mais informações sobre recursos, consulte Recursos de XAML.For more information on resources, see XAML Resources.

Noções básicas de modelagem de dadosData Templating Basics

Para demonstrar por que DataTemplate é importante, vamos examinar um exemplo de associação de dados.To demonstrate why DataTemplate is important, let's walk through a data binding example. Neste exemplo, temos um ListBox associado a uma lista de objetos Task.In this example, we have a ListBox that is bound to a list of Task objects. Cada objeto Task tem um TaskName (cadeia de caracteres), um Description (cadeia de caracteres), um Priority (int) e uma propriedade do tipo TaskType, que é um Enum com os valores Home e Work.Each Task object has a TaskName (string), a Description (string), a Priority (int), and a property of type TaskType, which is an Enum with values Home and Work.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:SDKSample"
  Title="Introduction to Data Templating Sample">
  <Window.Resources>
    <local:Tasks x:Key="myTodoList"/>

</Window.Resources>
  <StackPanel>
    <TextBlock Name="blah" FontSize="20" Text="My Task List:"/>
    <ListBox Width="400" Margin="10"
             ItemsSource="{Binding Source={StaticResource myTodoList}}"/>
  </StackPanel>
</Window>

Sem um DataTemplateWithout a DataTemplate

Sem um DataTemplate, nosso ListBox tem a seguinte aparência:Without a DataTemplate, our ListBox currently looks like this:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

O que acontece é que, sem instruções específicas, o ListBox por padrão chama ToString ao tentar exibir os objetos na coleção.What's happening is that without any specific instructions, the ListBox by default calls ToString when trying to display the objects in the collection. Portanto, se o objeto Task substituir o método ToString, o ListBox exibirá a representação de cadeia de caracteres de cada objeto de origem na coleção subjacente.Therefore, if the Task object overrides the ToString method, then the ListBox displays the string representation of each source object in the underlying collection.

Por exemplo, se a classe Task substituir o método ToString dessa maneira, em que name é o campo para a propriedade TaskName:For example, if the Task class overrides the ToString method this way, where name is the field for the TaskName property:

public override string ToString()
{
    return name.ToString();
}
Public Overrides Function ToString() As String
    Return _name.ToString()
End Function

Em seguida, o ListBox é semelhante ao seguinte:Then the ListBox looks like the following:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

No entanto, isso é inflexível e limitante.However, that is limiting and inflexible. Além disso, se você estiver ligando a dados XML, não poderá substituir ToString.Also, if you are binding to XML data, you wouldn't be able to override ToString.

Definindo um DataTemplate simplesDefining a Simple DataTemplate

A solução é definir um DataTemplate.The solution is to define a DataTemplate. Uma maneira de fazer isso é definir a propriedade ItemTemplate do ListBox como uma DataTemplate.One way to do that is to set the ItemTemplate property of the ListBox to a DataTemplate. O que você especificar em seu DataTemplate se tornará a estrutura visual do seu objeto de dados.What you specify in your DataTemplate becomes the visual structure of your data object. A DataTemplate a seguir é bem simples.The following DataTemplate is fairly simple. Estamos dando instruções de que cada item aparece como três elementos TextBlock dentro de um StackPanel.We are giving instructions that each item appears as three TextBlock elements within a StackPanel. Cada elemento TextBlock é associado a uma propriedade da classe Task.Each TextBlock element is bound to a property of the Task class.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}">
   <ListBox.ItemTemplate>
     <DataTemplate>
       <StackPanel>
         <TextBlock Text="{Binding Path=TaskName}" />
         <TextBlock Text="{Binding Path=Description}"/>
         <TextBlock Text="{Binding Path=Priority}"/>
       </StackPanel>
     </DataTemplate>
   </ListBox.ItemTemplate>
 </ListBox>

Os dados subjacentes para os exemplos neste tópico são uma coleção de objetos CLR.The underlying data for the examples in this topic is a collection of CLR objects. Se você estiver ligando a dados XML, os conceitos fundamentais são os mesmos, mas há uma pequena diferença sintática.If you are binding to XML data, the fundamental concepts are the same, but there is a slight syntactic difference. Por exemplo, em vez de ter Path=TaskName, defina XPath como @TaskName (se TaskName for um atributo do nó XML).For example, instead of having Path=TaskName, you would set XPath to @TaskName (if TaskName is an attribute of your XML node).

Agora, nosso ListBox é semelhante ao seguinte:Now our ListBox looks like the following:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

Criando o DataTemplate como um recursoCreating the DataTemplate as a Resource

No exemplo acima, definimos o DataTemplate embutido.In the above example, we defined the DataTemplate inline. É mais comum defini-lo na seção de recursos para que possa ser um objeto reutilizável, como no exemplo a seguir:It is more common to define it in the resources section so it can be a reusable object, as in the following example:

<Window.Resources>
<DataTemplate x:Key="myTaskTemplate">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>
</Window.Resources>

Agora, é possível usar o myTaskTemplate como recurso, como no exemplo a seguir:Now you can use myTaskTemplate as a resource, as in the following example:

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplate="{StaticResource myTaskTemplate}"/>

Como myTaskTemplate é um recurso, agora você pode usá-lo em outros controles que têm uma propriedade que usa um tipo DataTemplate.Because myTaskTemplate is a resource, you can now use it on other controls that have a property that takes a DataTemplate type. Como mostrado acima, para objetos ItemsControl, como o ListBox, é a propriedade ItemTemplate.As shown above, for ItemsControl objects, such as the ListBox, it is the ItemTemplate property. Para objetos ContentControl, é a propriedade ContentTemplate.For ContentControl objects, it is the ContentTemplate property.

A propriedade DataTypeThe DataType Property

A classe DataTemplate tem uma propriedade DataType que é muito semelhante à propriedade TargetType da classe Style.The DataTemplate class has a DataType property that is very similar to the TargetType property of the Style class. Portanto, em vez de especificar um x:Key para o DataTemplate no exemplo acima, você pode fazer o seguinte:Therefore, instead of specifying an x:Key for the DataTemplate in the above example, you can do the following:

<DataTemplate DataType="{x:Type local:Task}">
  <StackPanel>
    <TextBlock Text="{Binding Path=TaskName}" />
    <TextBlock Text="{Binding Path=Description}"/>
    <TextBlock Text="{Binding Path=Priority}"/>
  </StackPanel>
</DataTemplate>

Essa DataTemplate é aplicada automaticamente a todos os objetos de Task.This DataTemplate gets applied automatically to all Task objects. Observe que, nesse caso, o x:Key é definido implicitamente.Note that in this case the x:Key is set implicitly. Portanto, se você atribuir esse DataTemplate um valor de x:Key, você está substituindo o x:Key implícito e o DataTemplate não seria aplicado automaticamente.Therefore, if you assign this DataTemplate an x:Key value, you are overriding the implicit x:Key and the DataTemplate would not be applied automatically.

Se você estiver associando um ContentControl a uma coleção de objetos Task, o ContentControl não usará o DataTemplate acima automaticamente.If you are binding a ContentControl to a collection of Task objects, the ContentControl does not use the above DataTemplate automatically. Isso ocorre porque a associação em uma ContentControl precisa de mais informações para distinguir se você deseja associar a uma coleção inteira ou a objetos individuais.This is because the binding on a ContentControl needs more information to distinguish whether you want to bind to an entire collection or the individual objects. Se o ContentControl estiver rastreando a seleção de um tipo de ItemsControl, você poderá definir a propriedade Path da Associação de ContentControl como "/" para indicar que você está interessado no item atual.If your ContentControl is tracking the selection of an ItemsControl type, you can set the Path property of the ContentControl binding to "/" to indicate that you are interested in the current item. Para ver um exemplo, consulte Como associar a uma coleção e exibir informações com base na seleção.For an example, see Bind to a Collection and Display Information Based on Selection. Caso contrário, você precisa especificar o DataTemplate explicitamente definindo a propriedade ContentTemplate.Otherwise, you need to specify the DataTemplate explicitly by setting the ContentTemplate property.

A propriedade DataType é particularmente útil quando você tem uma CompositeCollection de diferentes tipos de objetos de dados.The DataType property is particularly useful when you have a CompositeCollection of different types of data objects. Para ver um exemplo, consulte Implementar um CompositeCollection.For an example, see Implement a CompositeCollection.

Adicionando mais ao DataTemplateAdding More to the DataTemplate

Os dados aparecem com as informações necessárias no momento, mas, sem dúvida, há espaço para melhoria.Currently the data appears with the necessary information, but there's definitely room for improvement. Vamos melhorar a apresentação adicionando um Border, um Gride alguns elementos de TextBlock que descrevem os dados que estão sendo exibidos.Let's improve on the presentation by adding a Border, a Grid, and some TextBlock elements that describe the data that is being displayed.


<DataTemplate x:Key="myTaskTemplate">
  <Border Name="border" BorderBrush="Aqua" BorderThickness="1"
          Padding="5" Margin="5">
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <TextBlock Grid.Row="0" Grid.Column="0" Text="Task Name:"/>
      <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=TaskName}" />
      <TextBlock Grid.Row="1" Grid.Column="0" Text="Description:"/>
      <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>
      <TextBlock Grid.Row="2" Grid.Column="0" Text="Priority:"/>
      <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Priority}"/>
    </Grid>
  </Border>
</DataTemplate>

A captura de tela a seguir mostra a ListBox com esse DataTemplatemodificado:The following screenshot shows the ListBox with this modified DataTemplate:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

Podemos definir HorizontalContentAlignment como Stretch no ListBox para ter certeza de que a largura dos itens ocupará todo o espaço:We can set HorizontalContentAlignment to Stretch on the ListBox to make sure the width of the items takes up the entire space:

<ListBox Width="400" Margin="10"
     ItemsSource="{Binding Source={StaticResource myTodoList}}"
     ItemTemplate="{StaticResource myTaskTemplate}" 
     HorizontalContentAlignment="Stretch"/>

Com a propriedade HorizontalContentAlignment definida como Stretch, o ListBox agora tem esta aparência:With the HorizontalContentAlignment property set to Stretch, the ListBox now looks like this:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

Usar DataTriggers para aplicar valores da propriedadeUse DataTriggers to Apply Property Values

A apresentação atual não nos informa se uma Task é uma tarefa de casa ou uma tarefa de escritório.The current presentation does not tell us whether a Task is a home task or an office task. Lembre-se de que o objeto Task tem uma propriedade TaskType do tipo TaskType, que é uma enumeração com os valores Home e Work.Remember that the Task object has a TaskType property of type TaskType, which is an enumeration with values Home and Work.

No exemplo a seguir, o DataTrigger define o BorderBrush do elemento chamado border como Yellow se a propriedade TaskType for TaskType.Home.In the following example, the DataTrigger sets the BorderBrush of the element named border to Yellow if the TaskType property is TaskType.Home.

<DataTemplate x:Key="myTaskTemplate">
<DataTemplate.Triggers>
  <DataTrigger Binding="{Binding Path=TaskType}">
    <DataTrigger.Value>
      <local:TaskType>Home</local:TaskType>
    </DataTrigger.Value>
    <Setter TargetName="border" Property="BorderBrush" Value="Yellow"/>
  </DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Agora, nosso aplicativo tem a seguinte aparência.Our application now looks like the following. As tarefas de casa são exibidas com uma borda amarela, enquanto as tarefas de escritório aparecem com uma borda verde-azulada:Home tasks appear with a yellow border and office tasks appear with an aqua border:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

Neste exemplo, o DataTrigger usa uma Setter para definir um valor de propriedade.In this example the DataTrigger uses a Setter to set a property value. As classes de gatilho também têm as propriedades EnterActions e ExitActions que permitem que você inicie um conjunto de ações, como animações.The trigger classes also have the EnterActions and ExitActions properties that allow you to start a set of actions such as animations. Além disso, também há uma classe MultiDataTrigger que permite aplicar alterações com base em vários valores de propriedade associados a dados.In addition, there is also a MultiDataTrigger class that allows you to apply changes based on multiple data-bound property values.

Uma maneira alternativa de obter o mesmo efeito é associar a propriedade BorderBrush à propriedade TaskType e usar um conversor de valor para retornar a cor com base no valor TaskType.An alternative way to achieve the same effect is to bind the BorderBrush property to the TaskType property and use a value converter to return the color based on the TaskType value. Criar o efeito acima usando um conversor é um pouco mais eficiente em termos de desempenho.Creating the above effect using a converter is slightly more efficient in terms of performance. Além disso, a criação do seu próprio conversor oferece mais flexibilidade, pois você fornecerá sua própria lógica.Additionally, creating your own converter gives you more flexibility because you are supplying your own logic. Por fim, a técnica escolhida depende do seu cenário e da sua preferência.Ultimately, which technique you choose depends on your scenario and your preference. Para obter informações sobre como escrever um conversor, consulte IValueConverter.For information about how to write a converter, see IValueConverter.

O que pertence a um DataTemplate?What Belongs in a DataTemplate?

No exemplo anterior, colocamos o gatilho dentro do DataTemplate usando a propriedade DataTemplate.Triggers.In the previous example, we placed the trigger within the DataTemplate using the DataTemplate.Triggers property. A Setter do gatilho define o valor de uma propriedade de um elemento (o elemento Border) que está dentro do DataTemplate.The Setter of the trigger sets the value of a property of an element (the Border element) that is within the DataTemplate. No entanto, se as propriedades às quais seus Setters se preocupam não forem Propriedades de elementos que estão dentro do DataTemplateatual, talvez seja mais adequado definir as propriedades usando uma Style que seja para a classe ListBoxItem (se o controle que você está associando for um ListBox).However, if the properties that your Setters are concerned with are not properties of elements that are within the current DataTemplate, it may be more suitable to set the properties using a Style that is for the ListBoxItem class (if the control you are binding is a ListBox). Por exemplo, se você quiser que o Trigger anime o valor de Opacity do item quando um mouse apontar para um item, você definirá gatilhos dentro de um estilo de ListBoxItem.For example, if you want your Trigger to animate the Opacity value of the item when a mouse points to an item, you define triggers within a ListBoxItem style. Para ver um exemplo, consulte a Amostra de introdução a estilo e modelagem.For an example, see the Introduction to Styling and Templating Sample.

Em geral, tenha em mente que o DataTemplate está sendo aplicado a cada um dos ListBoxItem gerados (para obter mais informações sobre como e onde ele é realmente aplicado, consulte a página ItemTemplate).In general, keep in mind that the DataTemplate is being applied to each of the generated ListBoxItem (for more information about how and where it is actually applied, see the ItemTemplate page.). Seu DataTemplate se preocupa apenas com a apresentação e a aparência dos objetos de dados.Your DataTemplate is concerned with only the presentation and appearance of the data objects. Na maioria dos casos, todos os outros aspectos da apresentação, como a aparência de um item quando ele é selecionado ou como o ListBox apresenta os itens, não pertencem à definição de um DataTemplate.In most cases, all other aspects of presentation, such as what an item looks like when it is selected or how the ListBox lays out the items, do not belong in the definition of a DataTemplate. Para ver um exemplo, consulte a seção Estilo e modelagem de um ItemsControl.For an example, see the Styling and Templating an ItemsControl section.

Escolhendo um DataTemplate com base nas propriedades do objeto de dadosChoosing a DataTemplate Based on Properties of the Data Object

Na seção A propriedade DataType, falamos que é possível definir diferentes modelos de dados para diferentes objetos de dados.In The DataType Property section, we discussed that you can define different data templates for different data objects. Isso é especialmente útil quando você tem uma CompositeCollection de diferentes tipos ou coleções com itens de tipos diferentes.That is especially useful when you have a CompositeCollection of different types or collections with items of different types. Na seção usar gatilhos de dados para aplicar valores de propriedade , mostramos que, se você tiver uma coleção do mesmo tipo de objeto de data, poderá criar um DataTemplate e, em seguida, usar gatilhos para aplicar as alterações com base nos valores de propriedade de todos os objetos de dados.In the Use DataTriggers to Apply Property Values section, we have shown that if you have a collection of the same type of data objects you can create a DataTemplate and then use triggers to apply changes based on the property values of each data object. Contudo, os gatilhos permitem aplicar valores da propriedade ou iniciar animações, mas não proporcionam flexibilidade para reconstruir a estrutura dos seus objetos de dados.However, triggers allow you to apply property values or start animations but they don't give you the flexibility to reconstruct the structure of your data objects. Alguns cenários podem exigir que você crie um DataTemplate diferente para objetos de dados do mesmo tipo, mas que têm propriedades diferentes.Some scenarios may require you to create a different DataTemplate for data objects that are of the same type but have different properties.

Por exemplo, se um objeto Task tiver um valor Priority de 1, talvez você queira lhe conferir uma aparência completamente diferente para funcionar como um alerta para si mesmo.For example, when a Task object has a Priority value of 1, you may want to give it a completely different look to serve as an alert for yourself. Nesse caso, você cria uma DataTemplate para a exibição dos objetos Task de alta prioridade.In that case, you create a DataTemplate for the display of the high-priority Task objects. Vamos adicionar o seguinte DataTemplate à seção de recursos:Let's add the following DataTemplate to the resources section:

<DataTemplate x:Key="importantTaskTemplate">
  <DataTemplate.Resources>
    <Style TargetType="TextBlock">
      <Setter Property="FontSize" Value="20"/>
    </Style>
  </DataTemplate.Resources>
  <Border Name="border" BorderBrush="Red" BorderThickness="1"
          Padding="5" Margin="5">
    <DockPanel HorizontalAlignment="Center">
      <TextBlock Text="{Binding Path=Description}" />
      <TextBlock>!</TextBlock>
    </DockPanel>
  </Border>
</DataTemplate>

Este exemplo usa a propriedade DataTemplate. Resources .This example uses the DataTemplate.Resources property. Os recursos definidos nessa seção são compartilhados pelos elementos dentro do DataTemplate.Resources defined in that section are shared by the elements within the DataTemplate.

Para fornecer a lógica para escolher qual DataTemplate usar com base no valor Priority do objeto de dados, crie uma subclasse de DataTemplateSelector e substitua o método SelectTemplate.To supply logic to choose which DataTemplate to use based on the Priority value of the data object, create a subclass of DataTemplateSelector and override the SelectTemplate method. No exemplo a seguir, o método SelectTemplate fornece a lógica para retornar o modelo apropriado com base no valor da propriedade Priority.In the following example, the SelectTemplate method provides logic to return the appropriate template based on the value of the Priority property. O modelo a ser retornado é encontrado nos recursos do elemento de Window enveloping.The template to return is found in the resources of the enveloping Window element.

using System.Windows;
using System.Windows.Controls;

namespace SDKSample
{
    public class TaskListDataTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate
            SelectTemplate(object item, DependencyObject container)
        {
            FrameworkElement element = container as FrameworkElement;

            if (element != null && item != null && item is Task)
            {
                Task taskitem = item as Task;

                if (taskitem.Priority == 1)
                    return
                        element.FindResource("importantTaskTemplate") as DataTemplate;
                else
                    return
                        element.FindResource("myTaskTemplate") as DataTemplate;
            }

            return null;
        }
    }
}

Namespace SDKSample
    Public Class TaskListDataTemplateSelector
        Inherits DataTemplateSelector
        Public Overrides Function SelectTemplate(ByVal item As Object, ByVal container As DependencyObject) As DataTemplate

            Dim element As FrameworkElement
            element = TryCast(container, FrameworkElement)

            If element IsNot Nothing AndAlso item IsNot Nothing AndAlso TypeOf item Is Task Then

                Dim taskitem As Task = TryCast(item, Task)

                If taskitem.Priority = 1 Then
                    Return TryCast(element.FindResource("importantTaskTemplate"), DataTemplate)
                Else
                    Return TryCast(element.FindResource("myTaskTemplate"), DataTemplate)
                End If
            End If

            Return Nothing
        End Function
    End Class
End Namespace

Em seguida, podemos declarar o TaskListDataTemplateSelector como um recurso:We can then declare the TaskListDataTemplateSelector as a resource:

<Window.Resources>
<local:TaskListDataTemplateSelector x:Key="myDataTemplateSelector"/>
</Window.Resources>

Para usar o recurso seletor de modelo, atribua-o à propriedade ItemTemplateSelector da ListBox.To use the template selector resource, assign it to the ItemTemplateSelector property of the ListBox. O ListBox chama o método SelectTemplate do TaskListDataTemplateSelector para cada um dos itens na coleção subjacente.The ListBox calls the SelectTemplate method of the TaskListDataTemplateSelector for each of the items in the underlying collection. A chamada passa o objeto de dados como o parâmetro de item.The call passes the data object as the item parameter. O DataTemplate retornado pelo método é aplicado a esse objeto de dados.The DataTemplate that is returned by the method is then applied to that data object.

<ListBox Width="400" Margin="10"
         ItemsSource="{Binding Source={StaticResource myTodoList}}"
         ItemTemplateSelector="{StaticResource myDataTemplateSelector}"
         HorizontalContentAlignment="Stretch"/>

Com o seletor de modelo em vigor, o ListBox agora aparece da seguinte maneira:With the template selector in place, the ListBox now appears as follows:

Captura de tela de exemplo de modelagem de dadosData templating sample screenshot

Isso conclui nossa discussão sobre este exemplo.This concludes our discussion of this example. Para ver a amostra completa, consulte Amostra da introdução à modelagem de dados.For the complete sample, see Introduction to Data Templating Sample.

Estilo e modelagem de um ItemsControlStyling and Templating an ItemsControl

Embora o ItemsControl não seja o único tipo de controle com o qual você pode usar um DataTemplate, é um cenário muito comum para associar um ItemsControl a uma coleção.Even though the ItemsControl is not the only control type that you can use a DataTemplate with, it is a very common scenario to bind an ItemsControl to a collection. Na seção o que pertence a um DataTemplate , discutimos que a definição de seu DataTemplate só deve se preocupar com a apresentação dos dados.In the What Belongs in a DataTemplate section we discussed that the definition of your DataTemplate should only be concerned with the presentation of data. Para saber quando não é adequado usar um DataTemplate é importante entender as diferentes propriedades de estilo e modelo fornecidas pelo ItemsControl.In order to know when it is not suitable to use a DataTemplate it is important to understand the different style and template properties provided by the ItemsControl. O exemplo a seguir foi desenvolvido para ilustrar a função de cada uma dessas propriedades.The following example is designed to illustrate the function of each of these properties. O ItemsControl neste exemplo está associado à mesma coleção de Tasks como no exemplo anterior.The ItemsControl in this example is bound to the same Tasks collection as in the previous example. Para fins de demonstração, os estilos e modelos deste exemplo são declarados como embutidos.For demonstration purposes, the styles and templates in this example are all declared inline.

<ItemsControl Margin="10"
              ItemsSource="{Binding Source={StaticResource myTodoList}}">
  <!--The ItemsControl has no default visual appearance.
      Use the Template property to specify a ControlTemplate to define
      the appearance of an ItemsControl. The ItemsPresenter uses the specified
      ItemsPanelTemplate (see below) to layout the items. If an
      ItemsPanelTemplate is not specified, the default is used. (For ItemsControl,
      the default is an ItemsPanelTemplate that specifies a StackPanel.-->
  <ItemsControl.Template>
    <ControlTemplate TargetType="ItemsControl">
      <Border BorderBrush="Aqua" BorderThickness="1" CornerRadius="15">
        <ItemsPresenter/>
      </Border>
    </ControlTemplate>
  </ItemsControl.Template>
  <!--Use the ItemsPanel property to specify an ItemsPanelTemplate
      that defines the panel that is used to hold the generated items.
      In other words, use this property if you want to affect
      how the items are laid out.-->
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <!--Use the ItemTemplate to set a DataTemplate to define
      the visualization of the data objects. This DataTemplate
      specifies that each data object appears with the Proriity
      and TaskName on top of a silver ellipse.-->
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <DataTemplate.Resources>
        <Style TargetType="TextBlock">
          <Setter Property="FontSize" Value="18"/>
          <Setter Property="HorizontalAlignment" Value="Center"/>
        </Style>
      </DataTemplate.Resources>
      <Grid>
        <Ellipse Fill="Silver"/>
        <StackPanel>
          <TextBlock Margin="3,3,3,0"
                     Text="{Binding Path=Priority}"/>
          <TextBlock Margin="3,0,3,7"
                     Text="{Binding Path=TaskName}"/>
        </StackPanel>
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <!--Use the ItemContainerStyle property to specify the appearance
      of the element that contains the data. This ItemContainerStyle
      gives each item container a margin and a width. There is also
      a trigger that sets a tooltip that shows the description of
      the data object when the mouse hovers over the item container.-->
  <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Control.Width" Value="100"/>
      <Setter Property="Control.Margin" Value="5"/>
      <Style.Triggers>
        <Trigger Property="Control.IsMouseOver" Value="True">
          <Setter Property="Control.ToolTip"
                  Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                          Path=Content.Description}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

Segue uma captura de tela do exemplo quando é renderizado:The following is a screenshot of the example when it is rendered:

Captura de tela de exemplo de ItemsControlItemsControl example screenshot

Observe que, em vez de usar o ItemTemplate, você pode usar o ItemTemplateSelector.Note that instead of using the ItemTemplate, you can use the ItemTemplateSelector. Consulte a seção anterior para ver um exemplo.Refer to the previous section for an example. Da mesma forma, em vez de usar o ItemContainerStyle, você tem a opção de usar o ItemContainerStyleSelector.Similarly, instead of using the ItemContainerStyle, you have the option to use the ItemContainerStyleSelector.

Duas outras propriedades relacionadas a estilo dos ItemsControl que não são mostradas aqui são GroupStyle e GroupStyleSelector.Two other style-related properties of the ItemsControl that are not shown here are GroupStyle and GroupStyleSelector.

Suporte para dados hierárquicosSupport for Hierarchical Data

Até o momento, examinamos apenas como associar a uma única coleção e exibi-la.So far we have only looked at how to bind to and display a single collection. Às vezes, você tem uma coleção que contém outras coleções.Sometimes you have a collection that contains other collections. A classe HierarchicalDataTemplate foi projetada para ser usada com tipos de HeaderedItemsControl para exibir esses dados.The HierarchicalDataTemplate class is designed to be used with HeaderedItemsControl types to display such data. No exemplo a seguir, ListLeagueList é uma lista de objetos League.In the following example, ListLeagueList is a list of League objects. Cada objeto League tem um Name e uma coleção de objetos Division.Each League object has a Name and a collection of Division objects. Cada Division tem um Name e uma coleção de objetos Team; cada objeto Team tem um Name.Each Division has a Name and a collection of Team objects, and each Team object has a Name.

<Window x:Class="SDKSample.Window1"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  Title="HierarchicalDataTemplate Sample"
  xmlns:src="clr-namespace:SDKSample">
  <DockPanel>
    <DockPanel.Resources>
      <src:ListLeagueList x:Key="MyList"/>

      <HierarchicalDataTemplate DataType    = "{x:Type src:League}"
                                ItemsSource = "{Binding Path=Divisions}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <HierarchicalDataTemplate DataType    = "{x:Type src:Division}"
                                ItemsSource = "{Binding Path=Teams}">
        <TextBlock Text="{Binding Path=Name}"/>
      </HierarchicalDataTemplate>

      <DataTemplate DataType="{x:Type src:Team}">
        <TextBlock Text="{Binding Path=Name}"/>
      </DataTemplate>
    </DockPanel.Resources>

    <Menu Name="menu1" DockPanel.Dock="Top" Margin="10,10,10,10">
        <MenuItem Header="My Soccer Leagues"
                  ItemsSource="{Binding Source={StaticResource MyList}}" />
    </Menu>

    <TreeView>
      <TreeViewItem ItemsSource="{Binding Source={StaticResource MyList}}" Header="My Soccer Leagues" />
    </TreeView>

  </DockPanel>
</Window>

O exemplo mostra que, com o uso de HierarchicalDataTemplate, você pode exibir facilmente os dados da lista que contêm outras listas.The example shows that with the use of HierarchicalDataTemplate, you can easily display list data that contains other lists. Segue uma captura de tela do exemplo.The following is a screenshot of the example.

Captura de tela de exemplo HierarchicalDataTemplateHierarchicalDataTemplate sample screenshot

Consulte tambémSee also