Возможно, слишком поздно, чтобы помочь вам, но для всех, кто ищет ответ, вы можете сделать это, используя Attached Behaviors и событие GridViewColumnHeader.Click (см. эту статью MSDN о сортировкеGridView при щелчке элемента заголовка).
Мой код был следующим;XAML:
<ListView Width="Auto" Height="Auto" Margin="12,12,12,12"
ItemsSource="{Binding SearchResults}"
behav:GridViewColumnHeaderClick.Command="{Binding SortViewCommand}">
(где «поведение» - это пространство имен для моего прикрепленного поведения).Прикрепленные классы поведения выглядят так:
public class GridViewColumnHeaderClick
{
public static readonly DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(GridViewColumnHeaderClick), new UIPropertyMetadata(null,
GridViewColumnHeaderClick.CommandChanged));
public static readonly DependencyProperty CommandBehaviourProperty =
DependencyProperty.RegisterAttached("CommandBehaviour", typeof(GridViewColumnHeaderClickCommandBehaviour), typeof(GridViewColumnHeaderClick),
new UIPropertyMetadata(null));
public static ICommand GetCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(CommandProperty);
}
public static void SetCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(CommandProperty, value);
}
public static GridViewColumnHeaderClickCommandBehaviour GetCommandBehaviour(DependencyObject obj)
{
return (GridViewColumnHeaderClickCommandBehaviour)obj.GetValue(CommandBehaviourProperty);
}
public static void SetCommandBehaviour(DependencyObject obj, GridViewColumnHeaderClickCommandBehaviour value)
{
obj.SetValue(CommandBehaviourProperty, value);
}
private static void CommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
GridViewColumnHeaderClick.GetOrCreateBehaviour(sender).Command = e.NewValue as ICommand;
}
private static GridViewColumnHeaderClickCommandBehaviour GetOrCreateBehaviour(DependencyObject element)
{
GridViewColumnHeaderClickCommandBehaviour returnVal = GridViewColumnHeaderClick.GetCommandBehaviour(element);
if (returnVal == null)
{
ListView typedElement = element as ListView;
if (typedElement == null)
{
throw new InvalidOperationException("GridViewColumnHeaderClick.Command property can only be set on instances of ListView");
}
returnVal = new GridViewColumnHeaderClickCommandBehaviour(typedElement);
GridViewColumnHeaderClick.SetCommandBehaviour(element, returnVal);
}
return returnVal;
}
}
и:
public class GridViewColumnHeaderClickCommandBehaviour
{
public GridViewColumnHeaderClickCommandBehaviour(ListView element)
{
element.AddHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(this.ClickEventHandler));
}
public ICommand Command { get; set; }
private void ClickEventHandler(object sender, RoutedEventArgs e)
{
ICommand localCommand = this.Command;
object parameter = e.OriginalSource as GridViewColumnHeader;
if ((localCommand != null) && localCommand.CanExecute(parameter))
{
localCommand.Execute(parameter);
}
}
}
, и тогда ваша команда может основываться на обработчике событий, описанном в статье MSDN:
private void SortResults(string sortBy, ListSortDirection direction)
{
ICollectionView dataView = CollectionViewSource.GetDefaultView(this.SearchResults); // where SearchResults is the data to which the ListView is bound
dataView.SortDescriptions.Clear();
SortDescription sortDescription = new SortDescription(sortBy, direction);
dataView.SortDescriptions.Add(sortDescription);
dataView.Refresh();
}
private void SortViewCommandHandler(object parameter)
{
GridViewColumnHeader typedParameter = parameter as GridViewColumnHeader;
ListSortDirection direction;
if (typedParameter != null)
{
if (typedParameter.Role != GridViewColumnHeaderRole.Padding)
{
if (typedParameter != this.previousSortHeader)
{
direction = ListSortDirection.Ascending;
}
else
{
if (this.previousSortDirection == ListSortDirection.Ascending)
{
direction = ListSortDirection.Descending;
}
else
{
direction = ListSortDirection.Ascending;
}
}
string headerLabel = typedParameter.Column.Header as string;
this.SortResults(headerLabel, direction);
if (direction == ListSortDirection.Ascending)
{
typedParameter.Column.HeaderTemplate =
Resources["HeaderTemplateArrowUp"] as DataTemplate;
}
else
{
typedParameter.Column.HeaderTemplate =
Resources["HeaderTemplateArrowDown"] as DataTemplate;
}
// Remove arrow from previously sorted header
if ((this.previousSortHeader != null) && (this.previousSortHeader != typedParameter))
{
this.previousSortHeader.Column.HeaderTemplate = null;
}
this.previousSortHeader = typedParameter;
this.previousSortDirection = direction;
}
}
}
Я еще не думал о MVVM-способе установки шаблона заголовка (вид, очевидно, должен быть привязан к чему-то здесь), так что вы сами там!
Обратите внимание, чтоЯ немного отклонился от статьи Джоша Смита в своей реализации присоединенного поведения - наличие отдельного класса облегчает несколько обработчиков с сохранением состояния, чем использование метода статического обработчика событий, поэтому в целом я придерживаюсь этого шаблона.