互联网上有很多的解决方案,试图填补WPF看似非常基本的遗漏。我真的很困惑什么是“最好”的方式。例如......我希望列标题中有小的向上/向下箭头来指示排序方向。显然有3种不同的方法可以做到这一点,有些使用代码,有些使用标记,有些使用标记加代码,而且所有看起来都像是黑客。
之前有没有人遇到过这个问题,并找到了他们完全满意的解决方案?似乎奇怪的是,WPF缺少这样一个基本的WinForms功能,需要被黑客攻击。
答案 0 :(得分:100)
我编写了一组附加属性来自动对GridView
进行排序,您可以查看here。它不处理向上/向下箭头,但可以轻松添加。
<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>
答案 1 :(得分:23)
MSDN has an easy way to perform sorting on columns。但是,示例并不完整 - 它们没有解释如何使用字形的数据模板。以下是我使用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中,您需要添加在排序方法中指定的两个DataTemplates:
<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
的{{1}}将字形保留在标题的右侧,让标签填充剩余的空格。我将LastChildFill
宽度绑定到DockPanel
的{{1}},因为我的列没有宽度,这使得它们可以自动调整内容。不过,我确实在列上设置了ActualWidth
,因此字形不会掩盖列标题。 GridViewColumnHeader
设置为空绑定,显示标题中指定的列名。
答案 2 :(得分:21)
这完全取决于你是否正在使用WPF Toolkit中的DataGrid,那么就有一个内置的排序,甚至是一个非常有用的多列排序。点击此处查看更多信息:
或者,如果您使用的是不支持排序的其他控件,我建议使用以下方法:
其次是:
答案 3 :(得分:5)
我使用MVVM,因此我使用Thomas作为参考创建了我自己的一些附加属性。当您单击标题时,它会在一列上进行排序,在升序和降序之间切换。它从一开始就使用第一列进行排序。它显示了Win7 / 8风格的字形。
通常,您所要做的就是将main属性设置为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;
}
}
}
答案 4 :(得分:2)
我修改了微软的方式,我在其中覆盖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
上,只需添加以下代码:
private void SortableListViewColumnHeaderClicked(object sender, RoutedEventArgs e)
{
((Controls.SortableListView)sender).GridViewColumnHeaderClicked(e.OriginalSource as GridViewColumnHeader);
}
其中Controls
只是您进行SortableListView
控件的命名空间的XAML ID。
因此,这确实会阻止排序方面的代码重复,您只需要记住如上所述处理事件。
答案 5 :(得分:2)
如果你有一个listview并将其转换为gridview,你可以通过这样做轻松地使你的gridview列标题可以点击。
<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。 这使我可以在ViewModel中单击所有View。
我只添加了这个,以便有多种方法来完成同样的事情。 我没有编写用于在标题中添加箭头按钮的代码,但是这将以XAML样式完成,您需要重新设计JanDotNet在其代码中具有的整个标题。
答案 6 :(得分:0)
查看:强>
<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;
}
}
答案 7 :(得分:0)
只想添加另一种简单的方法来使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;
}
答案 8 :(得分:0)
经过大量搜索,最终我发现这里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>
答案 9 :(得分:-1)
试试这个:
using System.ComponentModel;
youtItemsControl.Items.SortDescriptions.Add(new SortDescription("yourFavoritePropertyFromItem",ListSortDirection.Ascending);