В Интернете есть множество решений, пытающихся восполнить это, казалось бы, очень простое упущение WPF. Я действительно не понимаю, что было бы «лучшим» способом. Например ... Я хочу, чтобы в заголовке столбца были маленькие стрелки вверх / вниз, чтобы указывать направление сортировки. По-видимому, есть 3 разных способа сделать это: некоторые используют код, некоторые используют разметку, некоторые используют разметку плюс код, и все это похоже на взлом.
Кто-нибудь раньше сталкивался с этой проблемой и находил решение, которым полностью доволен? Кажется странным, что такая базовая функциональность WinForms отсутствует в WPF и ее необходимо взломать.
Ответы:
На самом деле все зависит от того, используете ли вы DataGrid из WPF Toolkit, тогда есть встроенная сортировка, даже сортировка по нескольким столбцам, которая очень полезна. Узнайте больше здесь:
Блог Винсента Сибалса
В качестве альтернативы, если вы используете другой элемент управления, который не поддерживает сортировку, я бы порекомендовал следующие методы:
Пользовательская сортировка Ли Гао
С последующим:
Быстрая сортировка Ли Гао
источник
Я написал набор прикрепленных свойств для автоматической сортировки
GridView
, вы можете проверить это здесь . Он не обрабатывает стрелки вверх / вниз, но его можно легко добавить.<ListView ItemsSource="{Binding Persons}" IsSynchronizedWithCurrentItem="True" util:GridViewSort.AutoSort="True"> <ListView.View> <GridView> <GridView.Columns> <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" util:GridViewSort.PropertyName="Name"/> <GridViewColumn Header="First name" DisplayMemberBinding="{Binding FirstName}" util:GridViewSort.PropertyName="FirstName"/> <GridViewColumn Header="Date of birth" DisplayMemberBinding="{Binding DateOfBirth}" util:GridViewSort.PropertyName="DateOfBirth"/> </GridView.Columns> </GridView> </ListView.View> </ListView>
источник
CollectionViewSource.GetDefaultView(MyList.ItemsSource).SortDescriptions.Add(new SortDescription("Number", ListSortDirection.Ascending));
не работает.В MSDN есть простой способ сортировки столбцов с глифами вверх / вниз. Однако пример не является полным - они не объясняют, как использовать шаблоны данных для глифов. Ниже показано, что мне нужно для работы с моим ListView. Это работает в .Net 4.
В вашем ListView вы должны указать обработчик событий, который запускается при нажатии на GridViewColumnHeader. Мой ListView выглядит так:
<ListView Name="results" GridViewColumnHeader.Click="results_Click"> <ListView.View> <GridView> <GridViewColumn DisplayMemberBinding="{Binding Path=ContactName}"> <GridViewColumn.Header> <GridViewColumnHeader Content="Contact Name" Padding="5,0,0,0" HorizontalContentAlignment="Left" MinWidth="150" Name="ContactName" /> </GridViewColumn.Header> </GridViewColumn> <GridViewColumn DisplayMemberBinding="{Binding Path=PrimaryPhone}"> <GridViewColumn.Header> <GridViewColumnHeader Content="Contact Number" Padding="5,0,0,0" HorizontalContentAlignment="Left" MinWidth="150" Name="PrimaryPhone"/> </GridViewColumn.Header> </GridViewColumn> </GridView> </ListView.View> </ListView>
В своем коде настройте код для обработки сортировки:
// Global objects BindingListCollectionView blcv; GridViewColumnHeader _lastHeaderClicked = null; ListSortDirection _lastDirection = ListSortDirection.Ascending; // Header click event void results_Click(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; } } // Sort code private void Sort(string sortBy, ListSortDirection direction) { blcv.SortDescriptions.Clear(); SortDescription sd = new SortDescription(sortBy, direction); blcv.SortDescriptions.Add(sd); blcv.Refresh(); }
А затем в свой XAML вам нужно добавить два DataTemplate, которые вы указали в методе сортировки:
<DataTemplate x:Key="HeaderTemplateArrowUp"> <DockPanel LastChildFill="True" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewColumnHeader}}}"> <Path x:Name="arrowUp" StrokeThickness="1" Fill="Gray" Data="M 5,10 L 15,10 L 10,5 L 5,10" DockPanel.Dock="Right" Width="20" HorizontalAlignment="Right" Margin="5,0,5,0" SnapsToDevicePixels="True"/> <TextBlock Text="{Binding }" /> </DockPanel> </DataTemplate> <DataTemplate x:Key="HeaderTemplateArrowDown"> <DockPanel LastChildFill="True" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GridViewColumnHeader}}}"> <Path x:Name="arrowDown" StrokeThickness="1" Fill="Gray" Data="M 5,5 L 10,10 L 15,5 L 5,5" DockPanel.Dock="Right" Width="20" HorizontalAlignment="Right" Margin="5,0,5,0" SnapsToDevicePixels="True"/> <TextBlock Text="{Binding }" /> </DockPanel> </DataTemplate>
Если для параметра
DockPanel
withLastChildFill
установлено значение true, глиф останется справа от заголовка, а метка заполнит остальное пространство. Я связалаDockPanel
ширины кActualWidth
из ,GridViewColumnHeader
потому что мои колонки не имеют ширины, которая позволяет им кнопкуШирину к содержимому.MinWidth
Тем не менее, я установил s для столбцов, чтобы глиф не закрывал заголовок столбца.TextBlock Text
Устанавливаются в пустом связывание , которое отображает имя столбца , указанное в заголовке.источник
<Window.Resources>
или<UserControl.Resources>
. HTHS;)headerClicked.Column.Header
(это текст заголовка) эквивалентно(headerClicked.Column.DisplayMemberBinding as Binding).Path.Path
(что является путем привязки). Сортировка по тексту заголовка не работает. Очень странно.Я использую MVVM, поэтому я создал несколько собственных свойств, используя Thomas в качестве ссылки. Он выполняет сортировку по одному столбцу за раз, когда вы нажимаете на заголовок, переключаясь между По возрастанию и По убыванию. Сортировка выполняется с самого начала по первому столбцу. И он показывает глифы в стиле Win7 / 8.
Обычно все, что вам нужно сделать, это установить для основного свойства значение true (но вы должны явно объявить GridViewColumnHeaders):
<Window xmlns:local="clr-namespace:MyProjectNamespace"> <Grid> <ListView local:App.EnableGridViewSort="True" ItemsSource="{Binding LVItems}"> <ListView.View> <GridView> <GridViewColumn DisplayMemberBinding="{Binding Property1}"> <GridViewColumnHeader Content="Prop 1" /> </GridViewColumn> <GridViewColumn DisplayMemberBinding="{Binding Property2}"> <GridViewColumnHeader Content="Prop 2" /> </GridViewColumn> </GridView> </ListView.View> </ListView> </Grid> <Window>
Если вы хотите выполнить сортировку по другому свойству, а не по отображению, вы должны заявить, что:
<GridViewColumn DisplayMemberBinding="{Binding Property3}" local:App.GridViewSortPropertyName="Property4"> <GridViewColumnHeader Content="Prop 3" /> </GridViewColumn>
Вот код для прикрепленных свойств, я люблю полениться и помещаю их в предоставленный App.xaml.cs:
using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data. using System.Windows.Media; using System.Windows.Media.Media3D; namespace MyProjectNamespace { public partial class App : Application { #region GridViewSort public static DependencyProperty GridViewSortPropertyNameProperty = DependencyProperty.RegisterAttached( "GridViewSortPropertyName", typeof(string), typeof(App), new UIPropertyMetadata(null) ); public static string GetGridViewSortPropertyName(GridViewColumn gvc) { return (string)gvc.GetValue(GridViewSortPropertyNameProperty); } public static void SetGridViewSortPropertyName(GridViewColumn gvc, string n) { gvc.SetValue(GridViewSortPropertyNameProperty, n); } public static DependencyProperty CurrentSortColumnProperty = DependencyProperty.RegisterAttached( "CurrentSortColumn", typeof(GridViewColumn), typeof(App), new UIPropertyMetadata( null, new PropertyChangedCallback(CurrentSortColumnChanged) ) ); public static GridViewColumn GetCurrentSortColumn(GridView gv) { return (GridViewColumn)gv.GetValue(CurrentSortColumnProperty); } public static void SetCurrentSortColumn(GridView gv, GridViewColumn value) { gv.SetValue(CurrentSortColumnProperty, value); } public static void CurrentSortColumnChanged( object sender, DependencyPropertyChangedEventArgs e) { GridViewColumn gvcOld = e.OldValue as GridViewColumn; if (gvcOld != null) { CurrentSortColumnSetGlyph(gvcOld, null); } } public static void CurrentSortColumnSetGlyph(GridViewColumn gvc, ListView lv) { ListSortDirection lsd; Brush brush; if (lv == null) { lsd = ListSortDirection.Ascending; brush = Brushes.Transparent; } else { SortDescriptionCollection sdc = lv.Items.SortDescriptions; if (sdc == null || sdc.Count < 1) return; lsd = sdc[0].Direction; brush = Brushes.Gray; } FrameworkElementFactory fefGlyph = new FrameworkElementFactory(typeof(Path)); fefGlyph.Name = "arrow"; fefGlyph.SetValue(Path.StrokeThicknessProperty, 1.0); fefGlyph.SetValue(Path.FillProperty, brush); fefGlyph.SetValue(StackPanel.HorizontalAlignmentProperty, HorizontalAlignment.Center); int s = 4; if (lsd == ListSortDirection.Ascending) { PathFigure pf = new PathFigure(); pf.IsClosed = true; pf.StartPoint = new Point(0, s); pf.Segments.Add(new LineSegment(new Point(s * 2, s), false)); pf.Segments.Add(new LineSegment(new Point(s, 0), false)); PathGeometry pg = new PathGeometry(); pg.Figures.Add(pf); fefGlyph.SetValue(Path.DataProperty, pg); } else { PathFigure pf = new PathFigure(); pf.IsClosed = true; pf.StartPoint = new Point(0, 0); pf.Segments.Add(new LineSegment(new Point(s, s), false)); pf.Segments.Add(new LineSegment(new Point(s * 2, 0), false)); PathGeometry pg = new PathGeometry(); pg.Figures.Add(pf); fefGlyph.SetValue(Path.DataProperty, pg); } FrameworkElementFactory fefTextBlock = new FrameworkElementFactory(typeof(TextBlock)); fefTextBlock.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center); fefTextBlock.SetValue(TextBlock.TextProperty, new Binding()); FrameworkElementFactory fefDockPanel = new FrameworkElementFactory(typeof(StackPanel)); fefDockPanel.SetValue(StackPanel.OrientationProperty, Orientation.Vertical); fefDockPanel.AppendChild(fefGlyph); fefDockPanel.AppendChild(fefTextBlock); DataTemplate dt = new DataTemplate(typeof(GridViewColumn)); dt.VisualTree = fefDockPanel; gvc.HeaderTemplate = dt; } public static DependencyProperty EnableGridViewSortProperty = DependencyProperty.RegisterAttached( "EnableGridViewSort", typeof(bool), typeof(App), new UIPropertyMetadata( false, new PropertyChangedCallback(EnableGridViewSortChanged) ) ); public static bool GetEnableGridViewSort(ListView lv) { return (bool)lv.GetValue(EnableGridViewSortProperty); } public static void SetEnableGridViewSort(ListView lv, bool value) { lv.SetValue(EnableGridViewSortProperty, value); } public static void EnableGridViewSortChanged( object sender, DependencyPropertyChangedEventArgs e) { ListView lv = sender as ListView; if (lv == null) return; if (!(e.NewValue is bool)) return; bool enableGridViewSort = (bool)e.NewValue; if (enableGridViewSort) { lv.AddHandler( GridViewColumnHeader.ClickEvent, new RoutedEventHandler(EnableGridViewSortGVHClicked) ); if (lv.View == null) { lv.Loaded += new RoutedEventHandler(EnableGridViewSortLVLoaded); } else { EnableGridViewSortLVInitialize(lv); } } else { lv.RemoveHandler( GridViewColumnHeader.ClickEvent, new RoutedEventHandler(EnableGridViewSortGVHClicked) ); } } public static void EnableGridViewSortLVLoaded(object sender, RoutedEventArgs e) { ListView lv = e.Source as ListView; EnableGridViewSortLVInitialize(lv); lv.Loaded -= new RoutedEventHandler(EnableGridViewSortLVLoaded); } public static void EnableGridViewSortLVInitialize(ListView lv) { GridView gv = lv.View as GridView; if (gv == null) return; bool first = true; foreach (GridViewColumn gvc in gv.Columns) { if (first) { EnableGridViewSortApplySort(lv, gv, gvc); first = false; } else { CurrentSortColumnSetGlyph(gvc, null); } } } public static void EnableGridViewSortGVHClicked( object sender, RoutedEventArgs e) { GridViewColumnHeader gvch = e.OriginalSource as GridViewColumnHeader; if (gvch == null) return; GridViewColumn gvc = gvch.Column; if(gvc == null) return; ListView lv = VisualUpwardSearch<ListView>(gvch); if (lv == null) return; GridView gv = lv.View as GridView; if (gv == null) return; EnableGridViewSortApplySort(lv, gv, gvc); } public static void EnableGridViewSortApplySort( ListView lv, GridView gv, GridViewColumn gvc) { bool isEnabled = GetEnableGridViewSort(lv); if (!isEnabled) return; string propertyName = GetGridViewSortPropertyName(gvc); if (string.IsNullOrEmpty(propertyName)) { Binding b = gvc.DisplayMemberBinding as Binding; if (b != null && b.Path != null) { propertyName = b.Path.Path; } if (string.IsNullOrEmpty(propertyName)) return; } ApplySort(lv.Items, propertyName); SetCurrentSortColumn(gv, gvc); CurrentSortColumnSetGlyph(gvc, lv); } public static void ApplySort(ICollectionView view, string propertyName) { if (string.IsNullOrEmpty(propertyName)) return; ListSortDirection lsd = ListSortDirection.Ascending; if (view.SortDescriptions.Count > 0) { SortDescription sd = view.SortDescriptions[0]; if (sd.PropertyName.Equals(propertyName)) { if (sd.Direction == ListSortDirection.Ascending) { lsd = ListSortDirection.Descending; } else { lsd = ListSortDirection.Ascending; } } view.SortDescriptions.Clear(); } view.SortDescriptions.Add(new SortDescription(propertyName, lsd)); } #endregion public static T VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject { return VisualUpwardSearch(source, x => x is T) as T; } public static DependencyObject VisualUpwardSearch( DependencyObject source, Predicate<DependencyObject> match) { DependencyObject returnVal = source; while (returnVal != null && !match(returnVal)) { DependencyObject tempReturnVal = null; if (returnVal is Visual || returnVal is Visual3D) { tempReturnVal = VisualTreeHelper.GetParent(returnVal); } if (tempReturnVal == null) { returnVal = LogicalTreeHelper.GetParent(returnVal); } else { returnVal = tempReturnVal; } } return returnVal; } } }
источник
Я адаптировал способ Microsoft, переопределив
ListView
элемент управления, чтобы создатьSortableListView
:public partial class SortableListView : ListView { private GridViewColumnHeader lastHeaderClicked = null; private ListSortDirection lastDirection = ListSortDirection.Ascending; public void GridViewColumnHeaderClicked(GridViewColumnHeader clickedHeader) { ListSortDirection direction; if (clickedHeader != null) { if (clickedHeader.Role != GridViewColumnHeaderRole.Padding) { if (clickedHeader != lastHeaderClicked) { direction = ListSortDirection.Ascending; } else { if (lastDirection == ListSortDirection.Ascending) { direction = ListSortDirection.Descending; } else { direction = ListSortDirection.Ascending; } } string sortString = ((Binding)clickedHeader.Column.DisplayMemberBinding).Path.Path; Sort(sortString, direction); lastHeaderClicked = clickedHeader; lastDirection = direction; } } } private void Sort(string sortBy, ListSortDirection direction) { ICollectionView dataView = CollectionViewSource.GetDefaultView(this.ItemsSource != null ? this.ItemsSource : this.Items); dataView.SortDescriptions.Clear(); SortDescription sD = new SortDescription(sortBy, direction); dataView.SortDescriptions.Add(sD); dataView.Refresh(); } }
((Binding)clickedHeader.Column.DisplayMemberBinding).Path.Path
Бит строки обрабатывает случаи, когда имена столбцов не совпадают с путями их привязки, чего не делает метод Microsoft.Я хотел перехватить
GridViewColumnHeader.Click
событие, чтобы больше не думать о нем, но не мог найти способа сделать это. В результате я добавляю в XAML следующее для каждогоSortableListView
:GridViewColumnHeader.Click="SortableListViewColumnHeaderClicked"
А затем для любого
Window
, содержащего любое количествоSortableListView
s, просто добавьте следующий код:private void SortableListViewColumnHeaderClicked(object sender, RoutedEventArgs e) { ((Controls.SortableListView)sender).GridViewColumnHeaderClicked(e.OriginalSource as GridViewColumnHeader); }
Где
Controls
просто идентификатор XAML для пространства имен, в котором вы создалиSortableListView
элемент управления.Таким образом, это предотвращает дублирование кода на стороне сортировки, вам просто нужно не забыть обрабатывать событие, как указано выше.
источник
Если у вас есть представление списка и вы превратили его в представление сетки, вы можете легко сделать заголовки столбцов представления сетки интерактивными, сделав это.
<Style TargetType="GridViewColumnHeader"> <Setter Property="Command" Value="{Binding CommandOrderBy}"/> <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self},Path=Content}"/> </Style>
Затем просто установите команду делегата в свой код.
public DelegateCommand CommandOrderBy { get { return new DelegateCommand(Delegated_CommandOrderBy); } } private void Delegated_CommandOrderBy(object obj) { throw new NotImplementedException(); }
Я предполагаю, что вы все знаете, как сделать здесь ICommand DelegateCommand. это позволило мне сохранить все мои View, нажимая на ViewModel.
Я добавил это только для того, чтобы было несколько способов сделать одно и то же. Я не писал код для добавления кнопок со стрелками в заголовок, но это будет сделано в стиле XAML, вам нужно будет переделать весь заголовок, который есть в коде JanDotNet.
источник
Решение, суммирующее все рабочие части существующих ответов и комментариев, включая шаблоны заголовков столбцов:
Посмотреть:
<ListView x:Class="MyNamspace.MyListView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" ItemsSource="{Binding Items}" GridViewColumnHeader.Click="ListViewColumnHeaderClick"> <ListView.Resources> <Style TargetType="Grid" x:Key="HeaderGridStyle"> <Setter Property="Height" Value="20" /> </Style> <Style TargetType="TextBlock" x:Key="HeaderTextBlockStyle"> <Setter Property="Margin" Value="5,0,0,0" /> <Setter Property="VerticalAlignment" Value="Center" /> </Style> <Style TargetType="Path" x:Key="HeaderPathStyle"> <Setter Property="StrokeThickness" Value="1" /> <Setter Property="Fill" Value="Gray" /> <Setter Property="Width" Value="20" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="Margin" Value="5,0,5,0" /> <Setter Property="SnapsToDevicePixels" Value="True" /> </Style> <DataTemplate x:Key="HeaderTemplateDefault"> <Grid Style="{StaticResource HeaderGridStyle}"> <TextBlock Text="{Binding }" Style="{StaticResource HeaderTextBlockStyle}" /> </Grid> </DataTemplate> <DataTemplate x:Key="HeaderTemplateArrowUp"> <Grid Style="{StaticResource HeaderGridStyle}"> <Path Data="M 7,3 L 13,3 L 10,0 L 7,3" Style="{StaticResource HeaderPathStyle}" /> <TextBlock Text="{Binding }" Style="{StaticResource HeaderTextBlockStyle}" /> </Grid> </DataTemplate> <DataTemplate x:Key="HeaderTemplateArrowDown"> <Grid Style="{StaticResource HeaderGridStyle}"> <Path Data="M 7,0 L 10,3 L 13,0 L 7,0" Style="{StaticResource HeaderPathStyle}" /> <TextBlock Text="{Binding }" Style="{StaticResource HeaderTextBlockStyle}" /> </Grid> </DataTemplate> </ListView.Resources> <ListView.View> <GridView ColumnHeaderTemplate="{StaticResource HeaderTemplateDefault}"> <GridViewColumn Header="Name" DisplayMemberBinding="{Binding NameProperty}" /> <GridViewColumn Header="Type" Width="45" DisplayMemberBinding="{Binding TypeProperty}"/> <!-- ... --> </GridView> </ListView.View> </ListView>
Кодовое поведение:
public partial class MyListView : ListView { GridViewColumnHeader _lastHeaderClicked = null; public MyListView() { InitializeComponent(); } private void ListViewColumnHeaderClick(object sender, RoutedEventArgs e) { GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader; if (headerClicked == null) return; if (headerClicked.Role == GridViewColumnHeaderRole.Padding) return; var sortingColumn = (headerClicked.Column.DisplayMemberBinding as Binding)?.Path?.Path; if (sortingColumn == null) return; var direction = ApplySort(Items, sortingColumn); 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 = Resources["HeaderTemplateDefault"] as DataTemplate; } _lastHeaderClicked = headerClicked; } public static ListSortDirection ApplySort(ICollectionView view, string propertyName) { ListSortDirection direction = ListSortDirection.Ascending; if (view.SortDescriptions.Count > 0) { SortDescription currentSort = view.SortDescriptions[0]; if (currentSort.PropertyName == propertyName) { if (currentSort.Direction == ListSortDirection.Ascending) direction = ListSortDirection.Descending; else direction = ListSortDirection.Ascending; } view.SortDescriptions.Clear(); } if (!string.IsNullOrEmpty(propertyName)) { view.SortDescriptions.Add(new SortDescription(propertyName, direction)); } return direction; } }
источник
Просто хотел добавить еще один простой способ сортировки WPF ListView
void SortListView(ListView listView) { IEnumerable listView_items = listView.Items.SourceCollection; List<MY_ITEM_CLASS> listView_items_to_list = listView_items.Cast<MY_ITEM_CLASS>().ToList(); Comparer<MY_ITEM_CLASS> scoreComparer = Comparer<MY_ITEM_CLASS>.Create((first, second) => first.COLUMN_NAME.CompareTo(second.COLUMN_NAME)); listView_items_to_list.Sort(scoreComparer); listView.ItemsSource = null; listView.Items.Clear(); listView.ItemsSource = listView_items_to_list; }
источник
После большого количества поисков, наконец, я нашел здесь просто https://www.wpf-tutorial.com/listview-control/listview-how-to-column-sorting/
private GridViewColumnHeader listViewSortCol = null; private SortAdorner listViewSortAdorner = null; private void GridViewColumnHeader_Click(object sender, RoutedEventArgs e) { GridViewColumnHeader column = (sender as GridViewColumnHeader); string sortBy = column.Tag.ToString(); if (listViewSortCol != null) { AdornerLayer.GetAdornerLayer(listViewSortCol).Remove(listViewSortAdorner); yourListView.Items.SortDescriptions.Clear(); } ListSortDirection newDir = ListSortDirection.Ascending; if (listViewSortCol == column && listViewSortAdorner.Direction == newDir) newDir = ListSortDirection.Descending; listViewSortCol = column; listViewSortAdorner = new SortAdorner(listViewSortCol, newDir); AdornerLayer.GetAdornerLayer(listViewSortCol).Add(listViewSortAdorner); yourListView.Items.SortDescriptions.Add(new SortDescription(sortBy, newDir)); }
Класс:
public class SortAdorner : Adorner { private static Geometry ascGeometry = Geometry.Parse("M 0 4 L 3.5 0 L 7 4 Z"); private static Geometry descGeometry = Geometry.Parse("M 0 0 L 3.5 4 L 7 0 Z"); public ListSortDirection Direction { get; private set; } public SortAdorner(UIElement element, ListSortDirection dir) : base(element) { this.Direction = dir; } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if(AdornedElement.RenderSize.Width < 20) return; TranslateTransform transform = new TranslateTransform ( AdornedElement.RenderSize.Width - 15, (AdornedElement.RenderSize.Height - 5) / 2 ); drawingContext.PushTransform(transform); Geometry geometry = ascGeometry; if(this.Direction == ListSortDirection.Descending) geometry = descGeometry; drawingContext.DrawGeometry(Brushes.Black, null, geometry); drawingContext.Pop(); } }
Xaml
<GridViewColumn Width="250"> <GridViewColumn.Header> <GridViewColumnHeader Tag="Name" Click="GridViewColumnHeader_Click">Name</GridViewColumnHeader> </GridViewColumn.Header> <GridViewColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Name}" ToolTip="{Binding Name}"/> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn>
источник
Попробуй это:
using System.ComponentModel; youtItemsControl.Items.SortDescriptions.Add(new SortDescription("yourFavoritePropertyFromItem",ListSortDirection.Ascending);
источник