2017-09-11 49 views
-1

我有一個TabControl,在每個TabItem中有一個DataGrid。每個DataGridRowDataGridRowHeader上都有一個按鈕,用於展開和摺疊RowDetails在TabItems之間切換後設置DataGridRow RowDetails

由於我使用行細節擴展功能,因此將VirtualizingPanel ScrollUnit設置爲Pixel,因此滾動更自然一些。

該程序捕獲哪些行已被擴展爲ObservableCollection<int>,該行包含要擴展的行索引。

當我切換到新的TabItem並回到原始的TabItem時,它會丟失哪些行已被擴展。

在更改DataContext後,我想使用ObservableCollection來重置展開的行。我曾在DataGridDataContextChanged事件中嘗試過。

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; 
    } 
} 

但是,它不會像在當前未在VirtualizingPanel行這樣做。

我該如何做到這一點?
我應該只是展開當前虛擬化的行嗎?
是否應該以編程方式操作DataGridScrollViewer?我如何計算ScrollViewer中不可見的行?
是否有另一個對象,其他DataGridRow我應該設置RowDetailsVisibility

回答

1

對於當前不在VirtualizingPanel中的行,沒有DataGridRow容器。這就是虛擬化的工作原理。

如果您想要在標籤開關之間保留一些信息,您應該將數據保存在您的視圖模型中。例如,您可以將DataGridRowHeader中的Button綁定到某些命令,該命令可以添加並刪除基礎數據類中集合的索引,即父母DataGridRow,TabItemTabControlDataContext

嘗試遍歷視覺DataGridRow容器將不起作用,除非您禁用UI虛擬化。這當然會導致性能問題。

+0

儘管我只是使用了代碼隱藏功能,但已經把大部分內容放在了裏面。我現在的問題是恢復存儲的數據。 – Hank

+0

還有一個問題:因此,如果一堆RowDetails設置爲可見,然後用戶將它們從VirtualizingPanel滾動,這會導致行被銷燬。 DataGrid在哪裏保存這些信息,因爲當你將它們滾動回視圖時它們仍然展開? – Hank

+1

這些元素是從先前的容器重新創建或重新使用的,並且由於某些屬性設置爲true或Visible,細節仍然可見。但這不會幫助你。 – mm8