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 el usuario hace clic en un encabezado de columna.
Ejemplo
El siguiente ejemplo define GridView con tres columnas que se enlazan con 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>
El ejemplo siguiente muestra los elementos de datos definidos como una ArrayList de objetos DateTime. ArrayList se define como un ItemsSource para el 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 las asignaciones de espacios de nombre que se definen en los metadatos de la página XAML. En el siguiente ejemplo se muestra la definición de metadatos.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://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, el ejemplo define un controlador de eventos para controlar el evento Click que se produce cuando presiona el botón del 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 manera que la dirección de orden cambia entre el orden ascendente y descendente cada vez que presiona el botón del encabezado de columna. El ejemplo siguiente muestra el controlador de eventos.
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
GridViewColumnHeader _lastHeaderClicked = null;
ListSortDirection _lastDirection = ListSortDirection.Ascending;
void GridViewColumnHeaderClickedHandler(object sender,
RoutedEventArgs e)
{
var 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;
}
}
var columnBinding = headerClicked.Column.DisplayMemberBinding as Binding;
var sortBy = columnBinding?.Path.Path ?? headerClicked.Column.Header as string;
Sort(sortBy, 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;
}
}
}
}
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 = 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 columnBinding = TryCast(headerClicked.Column.DisplayMemberBinding, Binding)
Dim sortBy = If(columnBinding?.Path.Path, TryCast(headerClicked.Column.Header, String))
Sort(sortBy, 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
End Class
El ejemplo siguiente muestra el algoritmo de orden invocado por el controlador de eventos para ordenar los datos. La ordenación se realiza mediante la creación de una nueva estructura SortDescription.
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();
}
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
Vea también
.NET Desktop feedback