2017-09-11 6 views
-1

Ich habe eine TabControl, in jedem TabItem gibt es eine DataGrid. Jede DataGridRow hat eine Schaltfläche auf der DataGridRowHeader, die die RowDetails erweitert und reduziert.Einstellung DataGridRow RowDetails Sichtbarkeit nach dem Umschalten zwischen TabItems

Da ich die Zeile Details Erweiterung Funktionalität verwenden, so haben Sie die ScrollUnit VirtualizationPanel auf Pixel, so Scrollen ist ein bisschen natürlicher.

Das Programm erfasst, welche Zeilen in einem ObservableCollection<int> erweitert wurden, der den zu erweiternden Zeilenindex enthält.

Wenn ich zu einem neuen TabItem und zurück zum ursprünglichen TabItem umschalte, verliert es, welche Reihen erweitert worden sind.

Nachdem die DataContext geändert wurde, möchte ich die ObservableCollection verwenden, um die erweiterten Zeilen zurückzusetzen. Ich habe dies im DataGridDataContextChanged Ereignis versucht.

public class DataGridBehaviors : Behavior<DataGrid>{ 
    protected override void OnAttached(){ 
     base.OnAttached(); 
     this.AssociatedObject.DataContextChanged += DataGrid_DataContextChanged; 
    } 

    protected override void OnDetaching(){ 
     this.AssociatedObject.DataContextChanged -= DataGrid_DataContextChanged; 
     base.OnDetaching(); 
    } 

    private void DataGrid_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e){ 
     ModuleGeometry oldModuleGeometry = (ModuleGeometry)e.OldValue; 
     ModuleGeometry newModuleGeometry = (ModuleGeometry)e.NewValue; 

     Task.Factory.StartNew(() => { 
      PerformRowExpansions(newModuleGeometry); 
     }); 

     ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(this.AssociatedObject); 
     if (scrollViewer != null){ 
      /* 
      * do some stuff 
      */ 
     } 
    } 

    private void PerformRowExpansions(ModuleGeometry newModuleGeometry){ 
     ObservableCollection<int> tempExpandedIndexes = new ObservableCollection<int>(newModuleGeometry.ExpandedIndexes); 
     newModuleGeometry.ExpandedIndexes = new ObservableCollection<int>(); 

     if (this.Dispatcher.CheckAccess()){ 
      foreach (int index in tempExpandedIndexes) 
      { 
       DataGridRow row = this.AssociatedObject.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow; 
       row.DetailsVisibility = Visibility.Visible; 
      } 
     } 
     else{ 
      this.Dispatcher.Invoke(new Action(() =>{ 
       foreach (int index in tempExpandedIndexes){ 
        DataGridRow row = this.AssociatedObject.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow; 
        row.DetailsVisibility = Visibility.Visible; 
       } 
      })); 
     } 
    } 

    private static T GetVisualChild<T>(DependencyObject parent) where T : Visual{ 
     T child = default(T); 

     int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < numVisuals; i++){ 
      Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
      child = v as T; 
      if (child == null) 
       child = GetVisualChild<T>(v); 
      if (child != null) 
       break; 
     } 
     return child; 
    } 
} 

Es ist jedoch nicht wie diese auf Reihen zu tun, die derzeit nicht in der VirtualizingPanel sind.

Wie kann ich das erreichen?
Soll ich nur die derzeit virtualisierten Zeilen erweitern?
Sollte die DataGridScrollViewer auch programmgesteuert manipuliert werden? Wie kann ich die Zeilen berücksichtigen, die im ScrollViewer nicht sichtbar sind?
Gibt es ein anderes Objekt, das andere DataGridRow, dass ich die RowDetailsVisibility einstellen sollte?

Antwort

1

Es gibt keine DataGridRow Container für die Zeilen, die derzeit nicht in der VirtualizingPanel sind. So funktioniert die Virtualisierung.

Wenn Sie Informationen zwischen Registerschaltern beibehalten möchten, sollten Sie die Daten in Ihren Ansichtsmodellen speichern. Sie könnten beispielsweise die Button in der DataGridRowHeader an einen Befehl binden, der Indizes aus einer Sammlung in der zugrunde liegenden Datenklasse hinzufügt und entfernt, d. H. Die DataContext der übergeordneten DataGridRow, TabItem oder TabControl.

Der Versuch, die visuellen DataGridRow Container zu durchlaufen, funktioniert nur, wenn Sie die UI-Virtualisierung deaktivieren. Und das kann natürlich zu Leistungsproblemen führen.

+0

Haben Sie das meiste von dem, worüber Sie gesprochen haben, obwohl ich nur Code-Behind benutze. Mein Problem besteht nun darin, diese gespeicherten Daten wiederherzustellen. – Hank

+0

Eine weitere Frage: Wenn also eine Reihe von RowDetails auf sichtbar gesetzt ist und der Benutzer sie vom VirtualizingPanel scrollt, werden die Zeilen zerstört. Wo behält das DataGrid diese Informationen, weil sie immer noch erweitert werden, wenn Sie sie zurück in die Ansicht scrollen? – Hank

+1

Die Elemente werden aus einem vorherigen Container neu erstellt oder wiederverwendet, und die Details sind weiterhin sichtbar, weil eine Eigenschaft auf "True" oder "Visible" gesetzt ist. Aber das wird dir nicht helfen. – mm8

Verwandte Themen