2010-10-19 85 views

回答

3

有幾個問題需要解決,以便做你想做的事情。最大的問題是,找出列的排序時間應該會更困難。我發現唯一的方法是識別列被排序,使其DataGrid.ItemsSource爲PagedCollectionView並在其SortDescriptions屬性上偵聽CollectionChanged事件。如果您的ItemsSource使用PagedCollectionView,並且可以排序的所有列都是DataGridBoundColumn(實際上是TemplateColumn以外的任何預構造),則此行爲應該與您想要執行的操作相當接近。

public class DataGridSortedColumnHighlightBehavior : Behavior<DataGrid> 
{ 

    private List<DataGridRow> rows = new List<DataGridRow>(); 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     AssociatedObject.LoadingRow += AssociatedObject_LoadingRow; 
     AssociatedObject.UnloadingRow += AssociatedObject_UnloadingRow; 

     if (AssociatedObject.ItemsSource == null) 
     { 
      AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated; 
     } 
     else 
     { 
      var collection = 
       ((AssociatedObject.ItemsSource as PagedCollectionView).SortDescriptions as INotifyCollectionChanged); 
      collection.CollectionChanged += DataGridSortedColumnHighlightBehavior_CollectionChanged; 
     } 
    } 

    void AssociatedObject_UnloadingRow(object sender, DataGridRowEventArgs e) 
    { 
     rows.Remove(e.Row); 
    } 

    void AssociatedObject_LoadingRow(object sender, DataGridRowEventArgs e) 
    { 
     rows.Add(e.Row); 
    } 

    private void AssociatedObject_LayoutUpdated(object sender, EventArgs e) 
    { 
     if (AssociatedObject.ItemsSource != null) 
     { 
      AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated; 
      var collection = 
       ((AssociatedObject.ItemsSource as PagedCollectionView).SortDescriptions as INotifyCollectionChanged); 
      collection.CollectionChanged += DataGridSortedColumnHighlightBehavior_CollectionChanged; 
     } 
    } 

    void DataGridSortedColumnHighlightBehavior_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     if(e.NewItems != null) 
     { 
      foreach(SortDescription sortDesc in e.NewItems) 
      { 
       foreach(var column in AssociatedObject.Columns) 
       { 
        var boundColumn = column as DataGridBoundColumn; 
        if (boundColumn == null) 
         continue; 
        if (boundColumn.Binding.Path.Path == sortDesc.PropertyName) 
        { 
         foreach (var row in rows) 
          ColorCell(column,row,Colors.Red); 
        } 
       } 
      } 
     } 
     if(e.OldItems != null) 
     { 
      foreach(SortDescription sortDesc in e.OldItems) 
      { 
       foreach(var column in AssociatedObject.Columns) 
       { 
        var boundColumn = column as DataGridBoundColumn; 
        if (boundColumn == null) 
         continue; 
        if (boundColumn.Binding.Path.Path == sortDesc.PropertyName) 
        { 
         foreach (var row in rows) 
          ColorCell(column,row,Colors.White); 
        } 
       } 
      } 
     } 
    } 

    private void ColorCell(DataGridColumn column, DataGridRow item, Color color) 
    { 
     var content = column.GetCellContent(item); 
     if (content == null) 
      return; 

     var parent = GetParent<DataGridCell>(content); 

     if (parent != null) 
      parent.Background = new SolidColorBrush(color); 

    } 

    public static T GetParent<T>(DependencyObject source) 
     where T : DependencyObject 
    { 
     DependencyObject parent = VisualTreeHelper.GetParent(source); 
     while (parent != null && !typeof(T).IsAssignableFrom(parent.GetType())) 
     { 
      parent = VisualTreeHelper.GetParent(parent); 
     } 
     return (T)parent; 
    }   
} 
+0

那近乎完美的作品。非常感謝您的回答,我注意到的唯一一件事情是它有時會出現滾動問題,但它仍然是一個非常大的幫助! – GotDibbs 2010-10-19 18:49:29

+0

滾動問題是由'DataGrid'虛擬化行的方式引起的。它只是實例化屏幕上可見的行數加1並將其保存在內存中。要解決此問題,您可能需要修改代碼以保留已排序的列的列表,並在加載行事件處理程序中突出顯示這些列的單元格。 – Stephan 2010-10-19 19:02:10

+0

Yeap這是我採取的確切路線。再次感謝! – GotDibbs 2010-10-19 19:20:33