Es gibt viele Lösungen im Internet, die versuchen, diese scheinbar sehr grundlegende Lücke in WPF zu schließen. Ich bin wirklich verwirrt darüber, was der "beste" Weg wäre. Zum Beispiel ... Ich möchte, dass die Spaltenüberschrift kleine Aufwärts- / Abwärtspfeile enthält, um die Sortierrichtung anzuzeigen. Es gibt anscheinend drei verschiedene Möglichkeiten, dies zu tun, einige mit Code, einige mit Markup, einige mit Markup-plus-Code und alle scheinen eher wie ein Hack zu sein.
Hat jemand dieses Problem schon einmal erlebt und eine Lösung gefunden, mit der er vollkommen zufrieden ist? Es scheint bizarr, dass eine solche grundlegende WinForms-Funktionalität in WPF fehlt und gehackt werden muss.
Antworten:
Es hängt wirklich davon ab, ob Sie das DataGrid aus dem WPF Toolkit verwenden, es gibt eine integrierte Sortierung, sogar eine mehrspaltige Sortierung, die sehr nützlich ist. Weitere Informationen finden Sie hier:
Vincent Sibals Blog
Wenn Sie alternativ ein anderes Steuerelement verwenden, das das Sortieren nicht unterstützt, würde ich die folgenden Methoden empfehlen:
Li Gaos benutzerdefinierte Sortierung
Gefolgt von:
Li Gaos schnelleres Sortieren
quelle
Ich habe eine Reihe von angehängten Eigenschaften geschrieben, um eine automatisch zu sortieren
GridView
. Sie können sie hier überprüfen . Der Aufwärts- / Abwärtspfeil wird nicht verarbeitet, kann aber problemlos hinzugefügt werden.<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>
quelle
CollectionViewSource.GetDefaultView(MyList.ItemsSource).SortDescriptions.Add(new SortDescription("Number", ListSortDirection.Ascending));
funktioniert nichtMSDN bietet eine einfache Möglichkeit, Spalten mit Aufwärts- / Abwärtszeichen zu sortieren . Das Beispiel ist jedoch nicht vollständig - sie erklären nicht, wie die Datenvorlagen für die Glyphen verwendet werden. Unten ist, was ich mit meiner ListView arbeiten muss. Dies funktioniert auf .Net 4.
In Ihrer ListView müssen Sie einen Ereignishandler angeben, der für einen Klick auf den GridViewColumnHeader ausgelöst werden soll. Meine ListView sieht folgendermaßen aus:
<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>
Richten Sie in Ihrem Code dahinter den Code für die Sortierung ein:
// 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(); }
Anschließend müssen Sie in Ihrer XAML zwei DataTemplates hinzufügen, die Sie in der Sortiermethode angegeben haben:
<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>
Wenn Sie das
DockPanel
with mitLastChildFill
set auf true verwenden, bleibt das Symbol rechts neben der Kopfzeile und das Etikett füllt den Rest des Leerzeichens aus. Ich habe dieDockPanel
Breite an dieActualWidth
von gebunden,GridViewColumnHeader
da meine Spalten keine Breite haben, sodass sie automatisch an den Inhalt angepasst werden können. Ich habe jedochMinWidth
s für die Spalten festgelegt, damit das Symbol den Spaltentitel nicht verdeckt. DasTextBlock Text
ist auf eine leere Bindung gesetzt, die den in der Kopfzeile angegebenen Spaltennamen anzeigt.quelle
<Window.Resources>
oder in den Ressourcen des Stammelements abgelegt werden<UserControl.Resources>
. HTHS;)headerClicked.Column.Header
(das ist der Kopfzeilentext) äquivalent zu(headerClicked.Column.DisplayMemberBinding as Binding).Path.Path
(das ist der Bindungspfad) ist. Das Sortieren im Kopfzeilentext funktioniert nicht. Sehr merkwürdig.Ich verwende MVVM, daher habe ich einige eigene angehängte Eigenschaften erstellt, wobei ich Thomas als Referenz verwendet habe. Wenn Sie auf die Überschrift klicken und zwischen Aufsteigend und Absteigend wechseln, wird jeweils nach einer Spalte sortiert. Es wird von Anfang an anhand der ersten Spalte sortiert. Und es zeigt Glyphen im Win7 / 8-Stil.
Normalerweise müssen Sie nur die Haupteigenschaft auf true setzen (Sie müssen jedoch die GridViewColumnHeaders explizit deklarieren):
<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>
Wenn Sie nach einer anderen Eigenschaft als der Anzeige sortieren möchten, müssen Sie Folgendes deklarieren:
<GridViewColumn DisplayMemberBinding="{Binding Property3}" local:App.GridViewSortPropertyName="Property4"> <GridViewColumnHeader Content="Prop 3" /> </GridViewColumn>
Hier ist der Code für die angehängten Eigenschaften. Ich bin gerne faul und füge sie in die bereitgestellte App.xaml.cs ein:
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; } } }
quelle
Ich habe eine Anpassung der Microsoft-Methode vorgenommen, bei der ich das
ListView
Steuerelement überschreibe , um Folgendes zu erstellenSortableListView
: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(); } }
Das
((Binding)clickedHeader.Column.DisplayMemberBinding).Path.Path
Zeilenbit behandelt die Fälle, in denen Ihre Spaltennamen nicht mit ihren Bindungspfaden übereinstimmen, was bei der Microsoft-Methode nicht der Fall ist.Ich wollte das
GridViewColumnHeader.Click
Ereignis abfangen , damit ich nicht mehr darüber nachdenken musste, aber ich konnte keinen Weg finden, dies zu tun. Als Ergebnis füge ich in XAML für jeden Folgendes hinzuSortableListView
:GridViewColumnHeader.Click="SortableListViewColumnHeaderClicked"
Und dann fügen Sie auf jedem
Window
, der eine beliebige Anzahl vonSortableListView
s enthält, einfach den folgenden Code hinzu:private void SortableListViewColumnHeaderClicked(object sender, RoutedEventArgs e) { ((Controls.SortableListView)sender).GridViewColumnHeaderClicked(e.OriginalSource as GridViewColumnHeader); }
Wo
Controls
ist nur die XAML-ID für den Namespace, in dem Sie dasSortableListView
Steuerelement erstellt haben.Dies verhindert also die Codeduplizierung auf der Sortierseite. Sie müssen nur daran denken, das Ereignis wie oben zu behandeln.
quelle
Wenn Sie eine Listenansicht haben und diese in eine Rasteransicht umwandeln, können Sie auf einfache Weise die Überschriften Ihrer Rasteransichts-Spalten anklickbar machen.
<Style TargetType="GridViewColumnHeader"> <Setter Property="Command" Value="{Binding CommandOrderBy}"/> <Setter Property="CommandParameter" Value="{Binding RelativeSource={RelativeSource Self},Path=Content}"/> </Style>
Legen Sie dann einfach einen Delegatenbefehl in Ihrem Code fest.
public DelegateCommand CommandOrderBy { get { return new DelegateCommand(Delegated_CommandOrderBy); } } private void Delegated_CommandOrderBy(object obj) { throw new NotImplementedException(); }
Ich gehe davon aus, dass Sie alle wissen, wie man den ICommand DelegateCommand hier erstellt. Dadurch konnte ich alle meine Ansichten im ViewModel klicken lassen.
Ich habe dies nur hinzugefügt, damit es mehrere Möglichkeiten gibt, dasselbe zu erreichen. Ich habe keinen Code zum Hinzufügen von Pfeilschaltflächen in die Kopfzeile geschrieben, aber dies würde im XAML-Stil erfolgen. Sie müssten die gesamte Kopfzeile, die JanDotNet in ihrem Code hat, neu gestalten.
quelle
Lösung, die alle Arbeitsteile vorhandener Antworten und Kommentare einschließlich Spaltenüberschriftenvorlagen zusammenfasst:
Aussicht:
<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>
Code Behinde:
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; } }
quelle
Ich wollte nur eine weitere einfache Möglichkeit hinzufügen, wie jemand die WPF-Listenansicht sortieren kann
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; }
quelle
Nach einer Menge Suche fand ich schließlich einfach hier 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)); }
Klasse:
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>
quelle
Versuche dies:
using System.ComponentModel; youtItemsControl.Items.SortDescriptions.Add(new SortDescription("yourFavoritePropertyFromItem",ListSortDirection.Ascending);
quelle