2011-05-05 48 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; 
     }