2010-10-19 5 views
2

J'ai un DataGrid dans mon application Silverlight que je voudrais mettre en évidence une colonne entière lorsque cette colonne est triée.Silverlight Datagrid: Mettre en évidence une colonne entière lorsque cette colonne est triée

Le concept est semblable à celui de la question précédente: Silverlight DataGrid: Highlight an entire column.

Des idées? J'ai pensé peut-être attacher un comportement à l'événement LayoutUpdated et vérifier une cellule pour voir si elle est dans une colonne triée?

Répondre

3

Il y a plusieurs problèmes que vous devez résoudre pour faire ce que vous voulez faire. Le plus gros problème est que le fait de savoir quand une colonne est triée est beaucoup plus difficile qu'elle ne devrait l'être. La seule façon que j'ai jamais trouvé pour identifier qu'une colonne a été triée pour faire un PagedCollectionView et écouter l'événement CollectionChanged sur sa propriété SortDescriptions. Si vous utilisez un PagedCollectionView pour votre ItemsSource et que toutes les colonnes pouvant être triées sont DataGridBoundColumn (en fait toutes les premades autres que TemplateColumn), ce comportement devrait être assez proche de ce que vous voulez faire.

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

Cela fonctionne presque parfaitement. Merci beaucoup pour votre réponse, la seule chose que j'ai remarquée est qu'elle a parfois un problème de défilement, mais c'est quand même une très grande aide! – GotDibbs

+0

Le problème de défilement est dû à la façon dont 'DataGrid' virtualise les lignes. Il ne fait qu'instancier le nombre de lignes visibles sur l'écran plus 1 et les garde en mémoire. Pour résoudre ce problème, vous devez probablement modifier le code afin de conserver une liste des colonnes triées et, dans le gestionnaire d'événements LoadingRow, mettre en évidence les cellules de ces colonnes. – Stephan

+0

Yeap c'est l'itinéraire exact que j'ai pris. Merci encore! – GotDibbs

Questions connexes