Vista de lista y vista de cuadrícula

La mayoría de las aplicaciones manipulan y muestran conjuntos de datos, como una galería de imágenes o un conjunto de mensajes de correo electrónico. El marco de trabajo de la interfaz de usuario de XAML proporciona los controles ListView y GridView que hacen más fácil mostrar y manipular datos en la aplicación.

Nota

ListView y GridView derivan de la clase ListViewBase , por lo que tienen la misma funcionalidad, pero muestran datos de forma diferente. En este artículo, los debates sobre la vista de lista se aplican a los controles ListView y GridView, a menos que se especifique lo contrario. Podemos hacer mención a clases como ListView o ListViewItem, pero el prefijo List se puede reemplazar por Grid para el equivalente de cuadrícula correspondiente (GridView o GridViewItem).

Los controles ListView y GridView proporcionan muchas ventajas al trabajar con colecciones. Ambos son fáciles de implementar y proporcionar la interfaz de usuario básica, la interacción y el desplazamiento mientras se pueden personalizar fácilmente. Y ambos se pueden enlazar a orígenes de datos dinámicos existentes o a datos codificados de forma rígida que se proporcionan en el propio XAML o en el código subyacente.

Ambos controles son flexibles para su uso en diversos escenarios, pero, en general, funcionan mejor con colecciones en las que todos los elementos tienen la misma estructura básica y apariencia, así como el mismo comportamiento de interacción. Es decir, todos deben realizar la misma acción cuando se hace clic en ellos (por ejemplo, para abrir un vínculo o examinar).

Comparar ListView y GridView

ListView

El control ListView muestra los datos apilados verticalmente en una sola columna. ListView funciona mejor para los elementos que tienen texto como punto focal y para las colecciones que están diseñadas para leerse de arriba abajo (por ejemplo, ordenadas alfabéticamente). Algunos casos de uso habituales de ListView son las listas de mensajes y los resultados de la búsqueda. Si necesita mostrar colecciones en varias columnas o en un formato similar a una tabla, no debe usar ListView. En su lugar, considere la posibilidad de usar un control DataGrid .

Captura de pantalla de una vista de lista de datos agrupados alfabéticamente.

GridView

El control GridView presenta una colección de elementos en filas y columnas que se pueden desplazar verticalmente. Los datos se apilan horizontalmente hasta que rellenan una columna y, a continuación, continúan con la fila siguiente de la columna. GridView funciona mejor para las colecciones que tienen imágenes como su punto focal o cuyos elementos se pueden leer de lado a lado o no se ordenan en un orden específico. Un caso de uso habitual de GridView es una galería de productos o de fotos.

Captura de pantalla de una biblioteca de contenido de fotos mostradas como una vista de cuadrícula.

¿Qué control de colección debes usar? Comparación con ItemsRepeater

Es importante comprender las diferencias entre estos tipos de controles antes de decidir cuál usar.

ListView y GridView

Los controles ListView y GridView enriquecidos con características funcionan de forma preconfigurada. No requieren personalización, pero se pueden personalizar fácilmente. Cada uno tiene su propia interfaz de usuario y experiencia de usuario integrada y está diseñada para mostrar casi cualquier tipo de colección tal como está.

ItemsRepeater

El control ItemsRepeater también se usa para mostrar colecciones, pero está diseñado como un bloque de creación para crear un control personalizado que se adapte a sus requisitos de interfaz de usuario concretos. No tiene las mismas características y funcionalidades integradas que ListView y GridView, por lo que deberá implementar las características o interacciones necesarias. Use ItemsRepeater si tiene una interfaz de usuario altamente personalizada que no se puede crear mediante ListView o GridView, o si el origen de datos requiere un comportamiento diferente para cada elemento.

Para más información sobre ItemsRepeater, lea su documentación sobre directrices y API.

UWP y WinUI 2

Importante

La información y los ejemplos de este artículo están optimizados para aplicaciones que usan el SDK de Aplicaciones para Windows y WinUI 3, pero generalmente son aplicables a las aplicaciones para UWP que usan WinUI 2. Consulte el material de referencia de las API de UWP para obtener información y ejemplos específicos de la plataforma.

Esta sección contiene información que necesita para usar el control en una aplicación para UWP o WinUI 2.

Las API de estos controles existen en el espacio de nombres Windows.UI.Xaml.Controls .

Se recomienda usar la versión más reciente de WinUI 2 para obtener los estilos y plantillas más actuales para todos los controles.

Crear una vista de lista o una vista de cuadrícula

Abra la aplicación WinUI 3 Gallery y vea ListView o GridView en acción.

La aplicación WinUI 3 Gallery incluye ejemplos interactivos de la mayoría de los controles, las características y la funcionalidad de WinUI 3. Obtenga la aplicación en Microsoft Store o el código fuente en GitHub.

ListView y GridView son de tipo ItemsControl, por lo que pueden contener una colección de elementos de cualquier tipo. Un control ListView o GridView debe tener elementos en su colección Items para poder mostrar cualquier elemento en la pantalla. Para rellenar la vista, puede agregar elementos directamente a la colección o establecer la propiedad ItemsSource en un origen de datos.

Precaución

Puede usar la propiedad Items o ItemsSource para rellenar la lista, pero no puede usar ambas al mismo tiempo. Si estableces la propiedad ItemsSource y agregas un elemento en XAML, el elemento agregado se omite. Si estableces la propiedad ItemsSource y decides agregar un elemento a la colección Items en código, se inicia una excepción.

Muchos de los ejemplos de este artículo rellenan directamente la colección Items por motivos de simplicidad. Sin embargo, es más común que los elementos de una lista provengan de un origen dinámico, como una lista de libros de una base de datos en línea. Usa la propiedad ItemsSource para tales fines.

Agregar elementos a un control ListView o GridView

Puedes agregar elementos a la colección ListView o GridView Items mediante XAML o código para producir el mismo resultado. Normalmente, agregarías elementos a través de XAML si tienes un pequeño número de elementos que no cambian y se definen fácilmente, o si generas los elementos en el código en tiempo de ejecución.

Método 1: Agregar elementos a la colección Items

  • Opción 1: Agregar elementos a través de XAML

    <!-- No corresponding C# code is needed for this example. -->
    
    <ListView x:Name="Fruits">
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
    </ListView>
    
  • Opción 2: Agregar elementos a través del código

    <StackPanel Name="FruitsPanel"></StackPanel>
    
    // Create a new ListView and add content.
    ListView Fruits = new ListView();
    Fruits.Items.Add("Apricot");
    Fruits.Items.Add("Banana");
    Fruits.Items.Add("Cherry");
    Fruits.Items.Add("Orange");
    Fruits.Items.Add("Strawberry");
    
    // Add the ListView to a parent container in the visual tree (which you created in the corresponding XAML file).
    FruitsPanel.Children.Add(Fruits);
    

Ambas opciones generan la misma vista de lista, como se muestra aquí:

Captura de pantalla de una vista de lista sencilla que muestra una lista de frutas.

Método 2: Agregar elementos estableciendo la propiedad ItemsSource

Normalmente, usaría un control ListView o GridView para mostrar datos de un origen como una base de datos o Internet. Para rellenar un control ListView o GridView desde un origen de datos, establezca su propiedad ItemsSource en una colección de elementos de datos. Este método funciona mejor si ListView o GridView va a contener objetos de clase personalizados, como se muestra en los ejemplos siguientes.

  • Opción 1: Establecer ItemsSource en el código

    Aquí, la propiedad ListView ItemsSource se establece en el código directamente en una instancia de una colección.

    <StackPanel x:Name="ContactPanel"></StackPanel>
    
    // Class definition should be provided within the namespace being used, outside of any other classes.
    
    this.InitializeComponent();
    
    // Instead of adding hard coded items to an ObservableCollection as shown here,
    //the data could be pulled asynchronously from a database or the internet.
    ObservableCollection<Contact> Contacts = new ObservableCollection<Contact>();
    
    // You create Contact objects by providing a first name, last name, and company for the Contact constructor.
    // They are then added to the ObservableCollection Contacts.
    Contacts.Add(new Contact("John", "Doe", "Contoso, LTD."));
    Contacts.Add(new Contact("Jane", "Doe", "Fabrikam, Inc."));
    Contacts.Add(new Contact("Santa", "Claus", "Alpine Ski House"));
    
    // Create a new ListView (or GridView) for the UI, and add content by setting ItemsSource
    ListView ContactsLV = new ListView();
    ContactsLV.ItemsSource = Contacts;
    
    // Add the ListView to a parent container in the visual tree (which you created in the corresponding XAML file)
    ContactPanel.Children.Add(ContactsLV);
    
  • Opción 2: establecer ItemsSource en XAML

    También puedes enlazar la propiedad ItemsSource a una colección en XAML. Aquí, ItemsSource se enlaza a una propiedad pública denominada Contacts, que expone la colección de datos privada de la página, denominada _contacts.

    <ListView x:Name="ContactsLV" ItemsSource="{x:Bind Contacts}"/>
    
    // Provide a class definition within the namespace being used, outside of any other classes.
    // These two declarations belong outside the main page class.
    private ObservableCollection<Contact> _contacts = new ObservableCollection<Contact>();
    
    public ObservableCollection<Contact> Contacts
    {
        get { return this._contacts; }
    }
    
    // Define this method within your main page class.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
    
        // Instead of hard coded items, the data could be pulled
        // asynchronously from a database or the internet.
        Contacts.Add(new Contact("John", "Doe", "Contoso, LTD."));
        Contacts.Add(new Contact("Jane", "Doe", "Fabrikam, Inc."));
        Contacts.Add(new Contact("Santa", "Claus", "Alpine Ski House"));
    }
    

Ambas opciones generarán la misma vista de lista, como se muestra en la captura de pantalla siguiente. (La vista de lista muestra la representación de cadena de cada elemento, porque no se define una plantilla de datos para este ejercicio).

Captura de pantalla que muestra una vista de lista simple con el conjunto de propiedades ItemsSource.

Importante

Sin una plantilla de datos definida, los objetos de clase personalizados aparecerán en la vista de lista con su valor de cadena solo si tienen un método ToString definido.

En la sección siguiente se explica con más detalle cómo representar visualmente elementos de clase simples y personalizados correctamente en una plantilla ListView o GridView.

Para obtener más información sobre el enlace de datos, consulta Introducción al enlace de datos.

Nota

Si necesita mostrar datos agrupados en la vista de lista, debe enlazar a una clase CollectionViewSource . CollectionViewSource actúa como proxy para la clase de colección en XAML y permite la compatibilidad con la agrupación. Para más información, consulta CollectionViewSource.

Personalización de la apariencia con una plantilla de datos

Mediante el uso de una plantilla de datos en un control ListView o GridView, puede definir cómo se van a visualizar los elementos y los datos. De manera predeterminada, un elemento de datos se muestra en la vista de lista como una representación de cadena del objeto de datos al que está enlazado. Puede mostrar la representación de cadena de una propiedad determinada del elemento de datos estableciendo DisplayMemberPath en esa propiedad.

Sin embargo, es posible que normalmente quiera mostrar una presentación más completa de los datos. Para especificar cómo se mostrarán los elementos de la vista de lista o la vista de cuadrícula, cree una clase DataTemplate . El XAML de DataTemplate define el diseño y la apariencia de los controles que se usan para mostrar un elemento individual. Los controles del diseño se pueden enlazar a las propiedades de un objeto de datos o pueden tener contenido estático alineado.

Importante

Al usar la extensión de marcado x:Bind en DataTemplate, debe especificar el tipo de datos (x:DataType) en la plantilla de datos.

Una plantilla de datos de ListView simple

En este ejemplo, el elemento de datos es una cadena simple. Para agregar una imagen a la izquierda de la cadena y mostrar la cadena en teal, defina DataTemplate insertada dentro de la definición de ListView. Este es el mismo control ListView que creó anteriormente mediante la opción 1 en el método 1.

<!--No corresponding code is needed for this example.-->
<ListView x:Name="FruitsList">
                <ListView.ItemTemplate>
                    <DataTemplate x:DataType="x:String">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="47"/>
                                <ColumnDefinition/>
                            </Grid.ColumnDefinitions>
                            <Image Source="Assets/placeholder.png" Width="32" Height="32"
                                HorizontalAlignment="Left" VerticalAlignment="Center"/>
                            <TextBlock Text="{x:Bind}" Foreground="Teal" FontSize="14"
                                Grid.Column="1" VerticalAlignment="Center"/>
                        </Grid>
                    </DataTemplate>
                </ListView.ItemTemplate>
                <x:String>Apricot</x:String>
                <x:String>Banana</x:String>
                <x:String>Cherry</x:String>
                <x:String>Orange</x:String>
                <x:String>Strawberry</x:String>
            </ListView>

Aquí se muestra cómo se muestran los elementos de datos al aplicar una plantilla de datos de ListView simple:

Captura de pantalla de la lista que se muestra después de aplicar una plantilla de datos de ListView simple.

Una plantilla de datos ListView para objetos de clase personalizados

En el ejemplo siguiente, el elemento de datos es un objeto Contact. Para agregar la imagen de contacto a la izquierda del nombre de contacto y la empresa, defina DataTemplate insertada dentro de la definición de ListView. Esta plantilla de datos listView se creó en la opción 2 en el método 2, como se mostró anteriormente.

<ListView x:Name="ContactsLV" ItemsSource="{x:Bind Contacts}">
    <ListView.ItemTemplate>
        <DataTemplate x:DataType="local:Contact">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <Image Grid.Column="0" Grid.RowSpan="2" Source="Assets/grey-placeholder.png" Width="32"
                    Height="32" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
                <TextBlock Grid.Column="1" Text="{x:Bind Name}" Margin="12,6,0,0"
                    Style="{ThemeResource BaseTextBlockStyle}"/>
                <TextBlock  Grid.Column="1" Grid.Row="1" Text="{x:Bind Company}" Margin="12,0,0,6"
                    Style="{ThemeResource BodyTextBlockStyle}"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Aquí se muestra cómo se muestran los elementos de datos al aplicar una plantilla de datos ListView para objetos de clase personalizados:

Captura de pantalla de una lista que se muestra después de aplicar una plantilla de datos ListView para objetos de clase personalizados.

Las plantillas de datos son la forma principal de definir la apariencia del control ListView. También pueden afectar significativamente al rendimiento si la lista contiene un gran número de elementos.

Puede definir la plantilla de datos insertada dentro de la definición ListView o GridView, como se muestra en el código anterior o por separado en una sección Recursos. Si la define fuera de la definición de ListView o GridView, debe asignarle un atributo x:Key a la plantilla de datos y asignarla a la propiedad ItemTemplate de ListView o GridView mediante esa clave.

Para obtener más información y ejemplos de cómo usar las plantillas de datos y los contenedores de elementos para definir la apariencia de los elementos de la lista o cuadrícula, consulta Plantillas y contenedores de elementos.

Cambiar el diseño de elementos

Al agregar elementos a un control ListView o GridView, ajusta automáticamente cada elemento de un contenedor de elementos y, a continuación, diseña todos los contenedores de elementos. La forma en que se diseñan estos contenedores de elementos depende de la propiedad ItemsPanel del control.

  • ListView, de forma predeterminada, usa ItemsStackPanel, que genera una lista vertical:

    Captura de pantalla de una vista de lista sencilla que muestra una lista vertical de elementos.

  • GridView usa ItemsWrapGrid, que agrega elementos horizontalmente y ajusta y se desplaza verticalmente:

    Captura de pantalla de una vista de cuadrícula sencilla que muestra una lista horizontal de elementos.

Puede modificar el diseño de los elementos ajustando las propiedades en el panel de elementos o puede reemplazar el panel predeterminado por otro panel.

Nota

Si cambia ItemsPanel, no deshabilite la virtualización. ItemsStackPanel y ItemsWrapGrid admiten la virtualización, por lo que estas clases son seguras para su uso. Si usas otro panel, es posible que deshabilites la virtualización y ralentices el rendimiento de la vista de lista. Para obtener más información, consulta los artículos sobre la vista de lista en Performance (Rendimiento).

En este ejemplo se muestra cómo crear un control ListView para diseñar sus contenedores de elementos en una lista horizontal cambiando la propiedad Orientation de ItemsStackPanel.

Dado que la vista de lista se desplaza verticalmente, de forma predeterminada, también debe ajustar algunas propiedades en el ScrollViewer interno de la vista de lista para que se desplace horizontalmente.

Importante

Los ejemplos siguientes se muestran con el ancho de la vista de lista sin restricciones, por lo que no se muestran las barras de desplazamiento horizontales. Si ejecuta este código, puede establecer que Width="180" ListView muestre las barras de desplazamiento.

<ListView Height="60"
          ScrollViewer.HorizontalScrollMode="Enabled"
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsStackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
</ListView>

Esta es la forma en que se muestra la lista:

Captura de pantalla de una vista de lista horizontal.

En el ejemplo siguiente, ListView diseña elementos en una lista de ajuste vertical mediante ItemsWrapGrid en lugar de ItemsStackPanel.

Importante

Debe restringir el alto de la vista de lista para forzar el control a encapsular los contenedores.

<ListView Height="100"
          ScrollViewer.HorizontalScrollMode="Enabled"
          ScrollViewer.HorizontalScrollBarVisibility="Auto"
          ScrollViewer.VerticalScrollMode="Disabled"
          ScrollViewer.VerticalScrollBarVisibility="Hidden">
    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <ItemsWrapGrid/>
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>
    <x:String>Apricot</x:String>
    <x:String>Banana</x:String>
    <x:String>Cherry</x:String>
    <x:String>Orange</x:String>
    <x:String>Strawberry</x:String>
</ListView>

Esta es la forma en que se muestra la lista:

Captura de pantalla de una vista de lista con un diseño de cuadrícula.

Si muestra datos agrupados en la vista de lista, ItemsPanel determina cómo se diseñan los grupos de elementos, no cómo se diseñan los elementos individuales. Por ejemplo, si usa el elemento ItemsStackPanel horizontal mostrado anteriormente para mostrar datos agrupados, los grupos se organizan horizontalmente, pero los elementos de cada grupo siguen apilados verticalmente, como se muestra aquí:

Captura de pantalla de una vista de lista horizontal agrupada.

Selección e interacción de elementos

Puede elegir entre varias maneras de permitir que los usuarios interactúen con una vista de lista. De forma predeterminada, los usuarios pueden seleccionar un solo elemento. Puedes cambiar la propiedad SelectionMode para habilitar la selección múltiple o para deshabilitar la selección. Puede establecer la propiedad IsItemClickEnabled para que los usuarios hagan clic en un elemento (por ejemplo, un botón) para invocar una acción en lugar de seleccionar el elemento.

Nota

ListView y GridView usan la enumeración ListViewSelectionMode para sus propiedades SelectionMode. IsItemClickEnabled se establece en False de forma predeterminada, por lo que solo tiene que establecerlo para habilitar el modo de clic.

En esta tabla se muestran las maneras en que un usuario puede interactuar con una vista de lista, y cómo se puedes responder a la interacción.

Para habilitar esta interacción: Usa esta configuración: Controla este evento: Usa esta propiedad para obtener el elemento seleccionado:
Sin interacción SelectionMode="None"
IsItemClickEnabled="False"
N/D N/A
Selección única SelectionMode="Single"
IsItemClickEnabled="False"
SelectionChanged Selecteditem
Selectedindex
Selección múltiple SelectionMode="Multiple"
IsItemClickEnabled="False"
SelectionChanged SelectedItems
Selección extendida SelectionMode="Extended"
IsItemClickEnabled="False"
SelectionChanged SelectedItems
Haga clic en SelectionMode="None"
IsItemClickEnabled="True"
ItemClick N/D

Nota

Puedes habilitar IsItemClickEnabled para generar un evento ItemClick, mientras que SelectionMode también está establecido en Single, Multiple o Extended. Si haces esto, primero se genera el evento ItemClick y luego se genera el evento SelectionChanged. En algunos casos (por ejemplo, si va a otra página en el controlador de eventos ItemClick), el evento SelectionChanged no se genera y el elemento no está seleccionado.

Puedes establecer estas propiedades en XAML o en código, como se muestra aquí:

<ListView x:Name="myListView" SelectionMode="Multiple"/>

<GridView x:Name="myGridView" SelectionMode="None" IsItemClickEnabled="True"/>
myListView.SelectionMode = ListViewSelectionMode.Multiple;

myGridView.SelectionMode = ListViewSelectionMode.None;
myGridView.IsItemClickEnabled = true;

Solo lectura

Puedes establecer la propiedad SelectionMode en ListViewSelectionMode.None para deshabilitar la selección de elementos. Esto coloca el control en modo de solo lectura, de modo que se use para mostrar datos, pero no para interactuar con él. Es decir, la selección de elementos está deshabilitada, pero el propio control no lo es.

Selección única

En esta tabla se describen las interacciones de teclado, mouse y entrada táctil cuando SelectionMode está establecido en Single.

Tecla modificadora Interacción
Ninguno
  • Los usuarios pueden seleccionar un solo elemento mediante la barra espaciadora, los clics del mouse o las pulsaciones.
  • Ctrl
  • Los usuarios pueden anular la selección de un solo elemento mediante la barra espaciadora, los clics del mouse o las pulsaciones.
  • Con las teclas de dirección, los usuarios pueden mover el foco independientemente de la selección.
  • Cuando SelectionMode se establece en Single, puede obtener el elemento de datos seleccionado de la propiedad SelectedItem . Puede obtener el índice en la colección del elemento seleccionado mediante la propiedad SelectedIndex . Si no se selecciona ningún elemento, SelectedItem es null y SelectedIndex es -1.

    Si intenta establecer un elemento que no está en la colección Items como SelectedItem, la operación se omite y SelectedItem es null. Sin embargo, si intenta establecer SelectedIndex en un índice que está fuera del intervalo de los elementos de la lista, se produce una excepción System.ArgumentException.

    Selección múltiple

    En esta tabla se describen las interacciones de teclado, mouse y táctil cuando SelectionMode está establecido en Multiple.

    Tecla modificadora Interacción
    Ninguno
  • Los usuarios pueden seleccionar varios elementos mediante la barra espaciadora, los clics del mouse o pulsaciones para seleccionar el elemento centrado.
  • Con las teclas de dirección, los usuarios pueden mover el foco independientemente de su selección.
  • Shift
  • Los usuarios pueden seleccionar varios elementos contiguos haciendo clic o pulsando en el primer elemento de la selección y, a continuación, haciendo clic o pulsando en el último elemento de la selección.
  • Con las teclas de dirección, los usuarios pueden seleccionar elementos contiguos a partir del elemento seleccionado al seleccionar la tecla Mayús.
  • Selección extendida

    En esta tabla se describen las interacciones de teclado, mouse y entrada táctil cuando SelectionMode está establecido en Extendido.

    Tecla modificadora Interacción
    Ninguno
  • El comportamiento es el mismo que la selección Single.
  • Ctrl
  • Los usuarios pueden seleccionar varios elementos mediante la barra espaciadora, los clics del mouse o pulsaciones para seleccionar el elemento centrado.
  • Con las teclas de dirección, los usuarios pueden mover el foco independientemente de la selección.
  • Shift
  • Los usuarios pueden seleccionar varios elementos contiguos haciendo clic o pulsando en el primer elemento de la selección y, a continuación, haciendo clic o pulsando en el último elemento de la selección.
  • Con las teclas de dirección, los usuarios pueden seleccionar elementos contiguos a partir del elemento seleccionado al seleccionar la tecla Mayús.
  • Cuando SelectionMode se establece en Multiple o Extended, puede obtener los elementos de datos seleccionados de la propiedad SelectedItems .

    Las propiedades SelectedIndex, SelectedItem y SelectedItems están sincronizadas. Por ejemplo, si establece SelectedIndex en -1, SelectedItem se establece en null y SelectedItems está vacío. Y si establece SelectedItem en null, SelectedIndex se establece en -1 y SelectedItems está vacío.

    En el modo de selección múltiple, SelectedItem contiene el elemento que se selecciona en primer lugar, y SelectedIndex contiene el índice del elemento que se seleccionó primero.

    Responder a los cambios de selección

    Para responder a cambios de selección en una vista de lista, controla el evento SelectionChanged. En el código del controlador de eventos, puedes obtener la lista de elementos seleccionados a partir de la propiedad SelectionChangedEventArgs.AddedItems. Puedes obtener los elementos cuya selección se anuló a partir de la propiedad SelectionChangedEventArgs.RemovedItems. Las colecciones AddedItems y RemovedItems contienen como máximo un elemento, a menos que los usuarios seleccionen un intervalo de elementos manteniendo presionada la tecla Mayús.

    En el ejemplo siguiente se muestra cómo controlar el evento SelectionChanged y obtener acceso a las distintas colecciones item:

    <StackPanel HorizontalAlignment="Right">
        <ListView x:Name="listView1" SelectionMode="Multiple"
                  SelectionChanged="ListView1_SelectionChanged">
            <x:String>Apricot</x:String>
            <x:String>Banana</x:String>
            <x:String>Cherry</x:String>
            <x:String>Orange</x:String>
            <x:String>Strawberry</x:String>
        </ListView>
        <TextBlock x:Name="selectedItem"/>
        <TextBlock x:Name="selectedIndex"/>
        <TextBlock x:Name="selectedItemCount"/>
        <TextBlock x:Name="addedItems"/>
        <TextBlock x:Name="removedItems"/>
    </StackPanel>
    
    private void ListView1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (listView1.SelectedItem != null)
        {
            selectedItem.Text =
                "Selected item: " + listView1.SelectedItem.ToString();
        }
        else
        {
            selectedItem.Text =
                "Selected item: null";
        }
        selectedIndex.Text =
            "Selected index: " + listView1.SelectedIndex.ToString();
        selectedItemCount.Text =
            "Items selected: " + listView1.SelectedItems.Count.ToString();
        addedItems.Text =
            "Added: " + e.AddedItems.Count.ToString();
        removedItems.Text =
            "Removed: " + e.RemovedItems.Count.ToString();
    }
    

    Modo de clic

    Puede cambiar una vista de lista para que los usuarios hagan clic en botones y otros elementos en lugar de seleccionarlos. Por ejemplo, esto resulta útil si la aplicación abre una nueva página cuando los usuarios hacen clic en un elemento de una lista o cuadrícula.

    Para habilitar este comportamiento:

    • Establece SelectionMode en None.
    • Establezca IsItemClickEnabled en True.
    • Controla el evento ItemClick para hacer algo cuando los usuarios hacen clic en un elemento.

    Aquí tienes una vista de lista con elementos en los que se puede hacer clic. El código del controlador de eventos ItemClick abre una nueva página en la aplicación.

    <ListView SelectionMode="None"
              IsItemClickEnabled="True"
              ItemClick="ListView1_ItemClick">
        <x:String>Page 1</x:String>
        <x:String>Page 2</x:String>
        <x:String>Page 3</x:String>
        <x:String>Page 4</x:String>
        <x:String>Page 5</x:String>
    </ListView>
    
    private void ListView1_ItemClick(object sender, ItemClickEventArgs e)
    {
        switch (e.ClickedItem.ToString())
        {
            case "Page 1":
                this.Frame.Navigate(typeof(Page1));
                break;
    
            case "Page 2":
                this.Frame.Navigate(typeof(Page2));
                break;
    
            case "Page 3":
                this.Frame.Navigate(typeof(Page3));
                break;
    
            case "Page 4":
                this.Frame.Navigate(typeof(Page4));
                break;
    
            case "Page 5":
                this.Frame.Navigate(typeof(Page5));
                break;
    
            default:
                break;
        }
    }
    

    Seleccionar un intervalo de elementos mediante programación

    A veces, es posible que tenga que manipular una selección de elementos listView mediante programación. Por ejemplo, puede mostrar un botón Seleccionar todo para permitir que los usuarios seleccionen todos los elementos de una lista. En este caso, normalmente no es muy eficaz agregar y quitar elementos de la colección SelectedItems uno por uno. Cada cambio de elemento provoca un evento SelectionChanged y, cuando se trabaja con los elementos directamente en lugar de trabajar con valores de índice, el elemento se des virtualiza.

    Es más eficaz usar los métodos SelectAll, SelectRange y DeselectRange para modificar la selección que para usar la propiedad SelectedItems. Estos métodos seleccionan (o anulan la selección) de elementos mediante intervalos de índices de elementos. Los elementos que están virtualizados permanecen virtualizados, porque solo se usa el índice. Se seleccionan todos los elementos en el intervalo especificado (o se anula la selección) independientemente de su estado de selección original. El evento SelectionChanged se produce solo una vez para cada llamada a estos métodos.

    Importante

    Solo debe llamar a estos métodos cuando la propiedad SelectionMode esté establecida en Multiple o Extended. Si llamas a SelectRange cuando SelectionMode es Single o None, se produce una excepción.

    Al seleccionar elementos mediante rangos de índice, utilice la propiedad SelectedRanges para obtener todos los intervalos seleccionados de la lista.

    Si la propiedad ItemsSource implementa IItemsRangeInfo y usa estos métodos para modificar la selección, las propiedades AddedItems y RemovedItems no se establecen en SelectionChangedEventArgs. Establecer estas propiedades requiere la desvirtualización del objeto del elemento. En su lugar, usa la propiedad SelectedRanges para obtener estos elementos.

    Para seleccionar todos los elementos en una colección, puedes llamar al método SelectAll. Sin embargo, no hay ningún método correspondiente para anular la selección de todos los elementos. Para anular la selección de todos los elementos, puedes llamar a DeselectRange y pasar una clase ItemIndexRange con un valor FirstIndex de 0 y un valor Length igual al número de elementos de la colección. Esto se muestra en el ejemplo siguiente, junto con una opción para seleccionar todos los elementos.

    <StackPanel Width="160">
        <Button Content="Select all" Click="SelectAllButton_Click"/>
        <Button Content="Deselect all" Click="DeselectAllButton_Click"/>
        <ListView x:Name="listView1" SelectionMode="Multiple">
            <x:String>Apricot</x:String>
            <x:String>Banana</x:String>
            <x:String>Cherry</x:String>
            <x:String>Orange</x:String>
            <x:String>Strawberry</x:String>
        </ListView>
    </StackPanel>
    
    private void SelectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.SelectAll();
        }
    }
    
    private void DeselectAllButton_Click(object sender, RoutedEventArgs e)
    {
        if (listView1.SelectionMode == ListViewSelectionMode.Multiple ||
            listView1.SelectionMode == ListViewSelectionMode.Extended)
        {
            listView1.DeselectRange(new ItemIndexRange(0, (uint)listView1.Items.Count));
        }
    }
    

    Para obtener información sobre cómo cambiar la apariencia de los elementos seleccionados, consulta Plantillas y contenedores de elementos.

    Arrastrar y colocar

    Los controles ListView y GridView admiten arrastrar y colocar elementos dentro de sus propios controles, y entre ellos y otros controles ListView y GridView. Para obtener más información sobre cómo implementar la funcionalidad de arrastrar y colocar, consulta Arrastrar y colocar.

    Obtención del código de ejemplo