2011-05-05 50 views
3

当用户在多列标题上按住Shift键时,WPF DataGrid具有允许进行多列排序的默认行为。有没有办法改变这种行为,以便Shift键不是必需的?我已经处理了数据网格上的排序事件,以便每列在三种排序状态(升序,降序和无排序)之间循环,只要按住Shift键,这一切都按预期工作,但我会就像这样做,以便DataGrid不会重置所有其他列上的排序,如果用户单击列标题来添加排序而不按shift键。WPF DataGrid MultiColumn排序不带Shift键

回答

1

我发现了一个似乎有点破解的解决方案,但它的工作原理。这篇文章让我指出了正确的方向:http://blogs.msdn.com/b/vinsibal/archive/2008/08/29/wpf-datagrid-tri-state-sorting-sample.aspx?PageIndex=2。这让我明白,每列的SortDirection并不以任何方式与ItemsSource SortDescriptions紧密相关。所以我所做的是订阅Datagrid的Sorting事件,并重置ItemsSource SortDescriptions集合中引用的每个列的SortDirection。显然,不按shift将清除每列的排序方向,但不会重置SortDescriptions。

0

我正在处理同样的问题,但没有人显示可以解决这个问题的代码。这个问题很古老,但我希望这个解决方案对寻求者有用。

(DataGrid.Items.SortDescriptions as INotifyCollectionChanged).CollectionChanged += OnGridCollectionChanged; 

private void OnGridCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) 
     { 
      var sortingCollection = (SortDescriptionCollection)sender; 
      foreach (var sortDesc in sortingCollection) 
      { 
       foreach (var column in SignaturesInImagingGrid.Columns) 
       { 
        if (column.SortMemberPath.Equals(sortDesc.PropertyName)) 
        { 
         column.SortDirection = sortDesc.Direction; 
        } 
       } 
      } 
     } 

<DataGrid Sorting="GridMultiColumnSortingEvent"> 

public static void GridMultiColumnSortingEvent(object sender, DataGridSortingEventArgs e) 
     { 
      var dgSender = (DataGrid)sender; 
      var cView = CollectionViewSource.GetDefaultView(dgSender.ItemsSource); 

      ListSortDirection direction = ListSortDirection.Ascending; 
      if (ContainsSortColumn((DataGrid)sender, e.Column.SortMemberPath)) 
      { 
       if (e.Column.SortDirection == null) 
       { 
        direction = ListSortDirection.Ascending; 
        ChangeSortColumn((DataGrid)sender, e.Column, direction); 
       } 
       else if (DirectionForColumn(cView, e.Column) == ListSortDirection.Ascending) 
       { 
        direction = ListSortDirection.Descending; 
        ChangeSortColumn((DataGrid)sender, e.Column, direction); 
       } 
       else if (DirectionForColumn(cView, e.Column) == ListSortDirection.Descending) 
       { 
        e.Column.SortDirection = null; 
        cView.SortDescriptions.Remove(cView.SortDescriptions.Where(item => item.PropertyName.Equals(e.Column.SortMemberPath)).FirstOrDefault()); 
        cView.Refresh(); 
       } 
      } 
      else 
      { 
       AddSortColumn((DataGrid)sender, e.Column.SortMemberPath, direction); 
       cView.Refresh(); 
      } 
      e.Handled = true; 
     } 

     private static ListSortDirection DirectionForColumn(ICollectionView cView, DataGridColumn column) => 
      cView.SortDescriptions.Where(item => item.PropertyName.Equals(column.SortMemberPath)) 
       .FirstOrDefault() 
       .Direction; 

     private static void AddSortColumn(DataGrid sender, string sortColumn, ListSortDirection direction) 
     { 
      var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource); 
      cView.SortDescriptions.Add(new SortDescription(sortColumn, direction)); 
      foreach (var col in sender.Columns.Where(x => x.SortMemberPath == sortColumn)) 
      { 
       col.SortDirection = direction; 
      } 
     } 

     private static void ChangeSortColumn(DataGrid sender, DataGridColumn column, ListSortDirection direction) 
     { 
      var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource); 
      string sortColumn = column.SortMemberPath; 

      foreach (var sortDesc in cView.SortDescriptions.ToList()) 
      { 
       if (sortDesc.PropertyName.Equals(sortColumn)) 
       { 
        cView.SortDescriptions.Remove(sortDesc); 
        break; 
       } 
      } 

      AddSortColumn(sender, sortColumn, direction); 
     } 

     private static bool ContainsSortColumn(DataGrid sender, string sortColumn) 
     { 
      var cView = CollectionViewSource.GetDefaultView(sender.ItemsSource); 
      foreach (var sortDesc in cView.SortDescriptions.ToList()) 
      { 
       if (sortDesc.PropertyName.Equals(sortColumn)) 
        return true; 
      } 
      return false; 
     }