Compartir a través de


Cómo: Ordenar una columna de GridView cuando se hace clic en un encabezado

En este ejemplo se muestra cómo crear un control ListView que implementa un modo de vista GridView y ordena el contenido de datos cuando un usuario hace clic en un encabezado de columna.

Ejemplo

En el ejemplo siguiente se define un objeto GridView con tres columnas que se enlazan a las propiedades Year, Month y Day de la estructura DateTime.

<GridView>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Year}" 
                  Header="Year"
                  Width="100"/>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Month}" 
                  Header="Month"
                  Width="100"/>
  <GridViewColumn DisplayMemberBinding="{Binding Path=Day}" 
                  Header="Day"
                  Width="100"/>
</GridView>

En el ejemplo siguiente se muestran los elementos de datos que se definen como una colección ArrayList de objetos DateTime. ArrayList se define como la propiedad ItemsSource del control ListView.

<ListView.ItemsSource>
  <s:ArrayList>
    <p:DateTime>1993/1/1 12:22:02</p:DateTime>
    <p:DateTime>1993/1/2 13:2:01</p:DateTime>
    <p:DateTime>1997/1/3 2:1:6</p:DateTime>
    <p:DateTime>1997/1/4 13:6:55</p:DateTime>
    <p:DateTime>1999/2/1 12:22:02</p:DateTime>
    <p:DateTime>1998/2/2 13:2:01</p:DateTime>
    <p:DateTime>2000/2/3 2:1:6</p:DateTime>
    <p:DateTime>2002/2/4 13:6:55</p:DateTime>
    <p:DateTime>2001/3/1 12:22:02</p:DateTime>
    <p:DateTime>2006/3/2 13:2:01</p:DateTime>
    <p:DateTime>2004/3/3 2:1:6</p:DateTime>
    <p:DateTime>2004/3/4 13:6:55</p:DateTime>
  </s:ArrayList>
</ListView.ItemsSource>

Los identificadores s y p de las etiquetas XAML hacen referencia a asignaciones de espacio de nombres que se definen en los metadatos de la página XAML. En el ejemplo siguiente se muestra la definición de los metadatos.

<Window      
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="ListViewSort.Window1"    
    xmlns:s="clr-namespace:System.Collections;assembly=mscorlib"
    xmlns:p="clr-namespace:System;assembly=mscorlib">

Para ordenar los datos según el contenido de una columna, en el ejemplo se define un controlador de eventos a fin de administrar el evento Click que se produce al presionar el botón de encabezado de columna. En el ejemplo siguiente se muestra cómo especificar un controlador de eventos para el control GridViewColumnHeader.

<ListView x:Name='lv' Height="150" HorizontalAlignment="Center" 
  VerticalAlignment="Center" 
  GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler"
 >

En el ejemplo se define el controlador de eventos de modo que el sentido de la ordenación cambie alternativamente entre ascendente y descendente cada vez que se presiona el botón de encabezado de columna. En el ejemplo siguiente se muestra el controlador de eventos.

    Partial Public Class Window1
        Inherits Window
        Public Sub New()
            InitializeComponent()
        End Sub

        Private _lastHeaderClicked As GridViewColumnHeader = Nothing
        Private _lastDirection As ListSortDirection = ListSortDirection.Ascending

        Private Sub GridViewColumnHeaderClickedHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim headerClicked As GridViewColumnHeader = TryCast(e.OriginalSource, GridViewColumnHeader)
            Dim direction As ListSortDirection

            If headerClicked IsNot Nothing Then
                If headerClicked.Role <> GridViewColumnHeaderRole.Padding Then
                    If headerClicked IsNot _lastHeaderClicked Then
                        direction = ListSortDirection.Ascending
                    Else
                        If _lastDirection = ListSortDirection.Ascending Then
                            direction = ListSortDirection.Descending
                        Else
                            direction = ListSortDirection.Ascending
                        End If
                    End If

                    Dim header As String = TryCast(headerClicked.Column.Header, String)
                    Sort(header, direction)

                    If direction = ListSortDirection.Ascending Then
                        headerClicked.Column.HeaderTemplate = TryCast(Resources("HeaderTemplateArrowUp"), DataTemplate)
                    Else
                        headerClicked.Column.HeaderTemplate = TryCast(Resources("HeaderTemplateArrowDown"), DataTemplate)
                    End If

                    ' Remove arrow from previously sorted header
                    If _lastHeaderClicked IsNot Nothing AndAlso _lastHeaderClicked IsNot headerClicked Then
                        _lastHeaderClicked.Column.HeaderTemplate = Nothing
                    End If


                    _lastHeaderClicked = headerClicked
                    _lastDirection = direction
                End If
            End If
        End Sub
public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();
    }

    GridViewColumnHeader _lastHeaderClicked = null;
    ListSortDirection _lastDirection = ListSortDirection.Ascending;

    void GridViewColumnHeaderClickedHandler(object sender,
                                            RoutedEventArgs e)
    {
        GridViewColumnHeader headerClicked =
              e.OriginalSource as GridViewColumnHeader;
        ListSortDirection direction;

        if (headerClicked != null)
        {
            if (headerClicked.Role != GridViewColumnHeaderRole.Padding)
            {
                if (headerClicked != _lastHeaderClicked)
                {
                    direction = ListSortDirection.Ascending;
                }
                else
                {
                    if (_lastDirection == ListSortDirection.Ascending)
                    {
                        direction = ListSortDirection.Descending;
                    }
                    else
                    {
                        direction = ListSortDirection.Ascending;
                    }
                }

                string header = headerClicked.Column.Header as string;
                Sort(header, direction);

                if (direction == ListSortDirection.Ascending)
                {
                    headerClicked.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowUp"] as DataTemplate;
                }
                else
                {
                    headerClicked.Column.HeaderTemplate =
                      Resources["HeaderTemplateArrowDown"] as DataTemplate;
                }

                // Remove arrow from previously sorted header
                if (_lastHeaderClicked != null && _lastHeaderClicked != headerClicked)
                {
                    _lastHeaderClicked.Column.HeaderTemplate = null;
                }


                _lastHeaderClicked = headerClicked;
                _lastDirection = direction;
            }
        }
    }

En el ejemplo siguiente se muestra el algoritmo de ordenación al que llama el controlador de eventos para ordenar los datos. La ordenación se realiza creando una nueva estructura SortDescription.

        Private Sub Sort(ByVal sortBy As String, ByVal direction As ListSortDirection)
            Dim dataView As ICollectionView = CollectionViewSource.GetDefaultView(lv.ItemsSource)

            dataView.SortDescriptions.Clear()
            Dim sd As New SortDescription(sortBy, direction)
            dataView.SortDescriptions.Add(sd)
            dataView.Refresh()
        End Sub
private void Sort(string sortBy, ListSortDirection direction)
{
    ICollectionView dataView =
      CollectionViewSource.GetDefaultView(lv.ItemsSource);

    dataView.SortDescriptions.Clear();
    SortDescription sd = new SortDescription(sortBy, direction);
    dataView.SortDescriptions.Add(sd);
    dataView.Refresh();
}

Vea también

Referencia

ListView

GridView

Conceptos

Información general sobre ListView

Información general sobre GridView

Otros recursos

Temas "Cómo..." sobre ListView