This article is currently in the process of being translated into Portuguese (~99% done).
The ItemsControl
O WPF tem uma ampla gama de controles para exibir uma lista de dados. Eles vêm em várias formas e formas e variam em quão complexo eles são e quanto trabalho eles executam para você. A variante mais simples é o ItemsControl, que é basicamente apenas um loop baseado em marcação - você precisa aplicar todos os estilos e modelos, mas em muitos casos, é exatamente o que você precisa.
Um exemplo simples de ItemsControl
Vamos começar com um exemplo muito simples, onde nós alimentamos manualmente o ItemsControl com um conjunto de itens. Isso deve mostrar o quão simples é o 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>
Como você pode ver, não há nada que mostre que estamos usando um controle para repetir os itens, em vez de apenas adicionar manualmente, por exemplo, 5 controles TextBlock - o ItemsControl é completamente sem aparência por padrão. Se você clicar em um dos itens, nada acontece, porque não há nenhum conceito de item (ns) selecionado (s) ou algo assim.
ItemsControl com ligação de dados
É claro que o ItemsControl não deve ser usado com itens definidos na marcação, como fizemos no primeiro exemplo. Como praticamente qualquer outro controle no WPF, o ItemsControl é feito para ligação de dados, onde usamos um modelo para definir como nossas classes de código devem ser apresentadas ao usuário.
Para demonstrar isso, preparei um exemplo onde exibimos uma lista TODO para o usuário e para mostrar o quão flexível tudo fica depois de definir seus próprios modelos, usei um controle ProgressBar para mostrar a conclusão atual percentagem. Primeiro algum código, depois uma captura de tela e depois uma explicação de tudo:
<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; }
}
}
A parte mais importante deste exemplo é o modelo que especificamos dentro do ItemsControl, usando uma tag DataTemplate dentro do ItemsControl.ItemTemplate. Nós adicionamos um painel Grid, para obter duas colunas: No primeiro temos um TextBlock, que mostrará o título do item TODO, e na segunda coluna temos um controle ProgressBar, cujo valor ligamos à propriedade Completion.
O modelo agora representa um TodoItem, que declaramos no arquivo Code-behind, onde também instanciamos um número deles e os adicionamos a uma lista. No final, essa lista é atribuída à propriedade ItemsSource do nosso ItemsControl, que então faz o resto do trabalho para nós. Cada item na lista é exibido usando nosso modelo, como você pode ver na captura de tela resultante.
A propriedade ItemsPanelTemplate
Nos exemplos acima, todos os itens são renderizados de cima para baixo, com cada item ocupando toda a linha. Isso acontece porque o ItemsControl joga todos os nossos itens em um StackPanel alinhado verticalmente por padrão. É muito fácil mudar, já que o ItemsControl permite que você altere qual tipo de painel é usado para armazenar todos os itens. Aqui está um exemplo:
<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>
Nós especificamos que o ItemsControl deve usar um WrapPanel como seu template, declarando um na propriedade ItemsPanelTemplate e apenas por diversão, nós lançamos um ItemTemplate que faz com que as strings sejam renderizadas como botões. Você pode usar qualquer um dos painéis do WPF, mas alguns são mais úteis do que outros.
Outro bom exemplo é o painel UniformGrid, onde podemos definir um número de colunas e depois ter nossos itens exibidos em colunas igualmente amplas:
<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 com barras de rolagem
Depois de começar a usar o ItemsControl, você pode se deparar com um problema muito comum: Por padrão, o ItemsControl não tem nenhuma barra de rolagem, o que significa que, se o conteúdo não couber, é apenas cortado. Isso pode ser visto tomando o primeiro exemplo deste artigo e redimensionando a janela:
O WPF torna isso muito fácil de resolver. Há várias soluções possíveis, por exemplo, você pode alterar o modelo usado pelo ItemsControl para incluir um controle ScrollViewer, mas a solução mais fácil é simplesmente jogar um ScrollViewer em volta do ItemsControl. Aqui está um exemplo:
<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>
Eu defini as duas opções de visibilidade para Auto, para torná-las visíveis apenas quando necessário. Como você pode ver na captura de tela, agora você pode rolar pela lista de itens.
Resumo
O ItemsControl é ótimo quando você quer controle total de como seus dados são exibidos, e quando você não precisa que nenhum conteúdo seja selecionável. Se você deseja que o usuário possa selecionar itens da lista, é melhor usar um dos outros controles, por exemplo, o ListBox ou o ListView. Eles serão descritos nos próximos capítulos.