首页 文章

在列 Headers 单击上进行WPF ListView / GridView排序的最佳方法是什么?

提问于
浏览
76

互联网上有很多解决方案试图填补WPF看似非常基本的遗漏 . 我真的很困惑"best"方式 . 例如......我希望列 Headers 中有小的向上/向下箭头来指示排序方向 . 显然有3种不同的方法可以做到这一点,有些使用代码,有些使用标记,有些使用标记加代码,而且所有看起来都像是黑客 .

有没有人遇到过这个问题,并找到了他们完全满意的解决方案?似乎奇怪的是,WPF缺少这样一个基本的WinForms功能,需要被黑客攻击 .

8 回答

  • 21

    这一切都取决于,如果你使用WPF工具包中的DataGrid,那么就有一个内置的排序,甚至是一个非常有用的多列排序 . 在这里查看更多:

    Vincent Sibals Blog

    或者,如果您使用的是不支持排序的其他控件,我建议使用以下方法:

    Li Gao's Custom Sorting

    其次是:

    Li Gao's Faster Sorting

  • 0

    我写了一组附加属性来自动排序 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>
    
  • 2

    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 并将 LastChildFill 设置为true将使 Headers 保持在 Headers 的右侧,并让标签填充剩余的空格 . 我将 DockPanel 宽度绑定到 GridViewColumnHeaderActualWidth 因为我的列没有宽度,这使得它们可以自动调整内容 . 不过,我确实在列上设置了 MinWidth ,因此字形不会掩盖列 Headers . TextBlock Text 设置为空绑定,显示 Headers 中指定的列名称 .

  • -1

    我使用MVVM,所以我创建了一些我自己的附加属性,使用Thomas作为参考 . 当您单击 Headers 时,它会在一列上进行排序,在升序和降序之间切换 . 它从一开始就使用第一列进行排序 . 它显示了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;
          }
      }
    }
    
  • 23

    我修改了微软的方式,我在其中覆盖 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"
    

    然后在任何包含任意数量的 SortableListViewWindow 上,只需添加以下代码:

    private void SortableListViewColumnHeaderClicked(object sender, RoutedEventArgs e)
            {
                ((Controls.SortableListView)sender).GridViewColumnHeaderClicked(e.OriginalSource as GridViewColumnHeader);
            }
    

    其中 Controls 只是您在其中创建 SortableListView 控件的命名空间的XAML ID .

    因此,这确实可以防止排序方面的代码重复,您只需要记住如上所述处理事件 .

  • 2

    如果您有listview并将其转换为gridview,则可以通过执行此操作轻松地使gridview列 Headers 可单击 .

    <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中单击 .

    我只添加了这个,以便有多种方法来完成同样的事情 . 我没有编写用于在 Headers 中添加箭头按钮的代码,但是这将以XAML样式完成,您需要重新设计JanDotNet在其代码中具有的整个标头 .

  • 5

    解决方案总结了现有答案和评论的所有工作部分,包括列 Headers 模板:

    View:

    <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;
        }
    }
    
  • 101

    试试这个:

    using System.ComponentModel;
    youtItemsControl.Items.SortDescriptions.Add(new SortDescription("yourFavoritePropertyFromItem",ListSortDirection.Ascending);
    

相关问题