This article has been localized into Spanish by the community.
El control ItemsControl
WPF cuenta con una amplia gama de controles para mostrar una lista de datos. Tales controles vienen en distintos aspectos y formas, y varían en su complejidad y cuánto trabajo realizan por ti. La variante más simple es ItemsControl, que es más o menos un bucle basado en una plantilla - debes indicar todos los estilos y plantillas, pero, en muchos casos, es lo único que necesitas.
Un ejemplo simple de ItemsControl.
Empecemos con un ejemplo muy simple, donde llenaremos a mano el control ItemsControl con un conjunto de elementos. Esto debería mostrarte cuán simple es este control:
<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 puede ver, no hay nada que muestre que estamos usando un control para repetir los elementos en lugar de solo agregar manualmente, por ejemplo 5 controles TextBlock - ItemsControl es completamente inútil por defecto. Si hace clic en uno de los elementos, no sucede nada, porque no hay un concepto de elementos seleccionados o cualquier cosa como eso.
ItemsControl con enlace de datos.
Por supuesto, el ItemsControl no debe usarse con elementos definidos en el marcado, como hicimos en el primer ejemplo. Como casi cualquier otro control en WPF, ItemsControl está hecho para el enlace de datos, donde usamos una plantilla para definir cómo se deben presentar nuestras clases de código subyacente al usuario.
Para demostrarlo, he preparado un ejemplo en el que mostramos TODA una lista al usuario, para mostrarle cuán flexible se vuelve todo una vez que define tus propias plantillas, he usado un control ProgressBar para mostrarte el porcentaje de finalización actual. Primero un código, luego una captura de pantalla y luego una explicación de todo esto:
<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; }
}
}
La parte más importante de este ejemplo es la plantilla que especificamos dentro de ItemsControl, usando una etiqueta DataTemplate dentro de ItemsControl.ItemTemplate. Agregamos un panel de cuadrícula para obtener dos columnas: en la primera tenemos un TextBlock, que mostrará el título del elemento TODO, y en la segunda columna tenemos un control ProgressBar, cuyo valor vinculamos a la propiedad Completion.
La plantilla ahora representa un TodoItem, que declaramos en el archivo de Código subyacente, donde también instanciamos un número de ellos y los agregamos a una lista. Al final, esta lista se asigna a la propiedad ItemsSource de nuestro ItemsControl, que luego hace el resto del trabajo por nosotros. Cada elemento en la lista se muestra utilizando nuestra plantilla, como puede ver en la captura de pantalla resultante.
La propiedad ItemsPanelTemplate.
En los ejemplos anteriores, todos los elementos se representan de arriba a abajo, y cada elemento ocupa la fila completa. Esto sucede porque ItemsControl arroja todo nuestros artículos en un StackPanel alineado verticalmente por defecto. Sin embargo, es muy fácil cambiar, ya que ItemsControl le permite cambiar el tipo de panel que se usará para contener todos los artículos. Aquí hay un ejemplo:
<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>
Especificamos que ItemsControl debe usar un WrapPanel como plantilla declarando uno en la propiedad ItemsPanelTemplate y solo para divertirnos, agregamos un ItemTemplate que hace que las cadenas se representen como botones. Puede usar cualquiera de los paneles WPF, pero algunos son más útiles que otros.
Otro buen ejemplo es el panel UniformGrid, donde podemos definir una serie de columnas y luego mostrar nuestros elementos en columnas igualmente anchas:
<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 con barras de desplazamiento.
Una vez que comience a usar ItemsControl, es posible que se encuentre con un problema muy común: de manera predeterminada, ItemsControl no tiene barras de desplazamiento, lo que significa que si el contenido no encaja, solo se recorta. Esto se puede ver tomando nuestro primer ejemplo de este artículo y redimensionando la ventana:
Sin embargo, WPF hace que esto sea muy fácil de resolver. Hay varias soluciones posibles, por ejemplo, puede modificar la plantilla utilizada por ItemsControl para incluir un control ScrollViewer, pero la solución más fácil es simplemente lanzar un ScrollViewer alrededor de ItemsControl. Aquí hay un ejemplo:
<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>
Establecí las dos opciones de visibilidad en Automático, para que solo sean visibles cuando sea necesario. Como puede ver en la captura de pantalla, ahora puede desplazarse por la lista de artículos.
Resumen
ItemsControl es excelente cuando desea un control total de cómo se muestran sus datos y cuando no necesita que su contenido sea seleccionable. Si tu deseas que el usuario pueda seleccionar elementos de la lista, entonces es mejor que tenga uno de los otros controles, por ejemplo ListBox o ListView. Éstos se describirá en los próximos capítulos.