2017-09-11 20 views
-1

私はTabControlを持っています、それぞれTabItemにはDataGridがあります。各DataGridRowにはDataGridRowHeaderにボタンがあり、RowDetailsを展開して折りたたみます。TabItem間の切り替え後に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コンテナはありません。それが仮想化の仕組みです。

タブスイッチ間で情報を保持する場合は、永続化するデータをビューモデルに保存する必要があります。たとえば、DataGridRowHeaderButtonを、基礎となるデータクラスのコレクションからインデックスを追加および削除するコマンドにバインドすることができます。つまり、、TabItemまたはTabControlDataContextです。

UI仮想化を無効にしない限り、ビジュアルDataGridRowコンテナを反復処理することはできません。もちろんこれはパフォーマンスの問題につながります。

+0

私はちょうどコードビハインドを使用していますが、あなたが話したことのほとんどを入れました。私の問題は、その保存されたデータを復元することです。 – Hank

+0

もう1つ質問:RowDetailsの束がvisibleに設定されている場合に、ユーザーがそれらをVirtualizingPanelからスクロールすると、行が破棄されます。 DataGridはこの情報をどこに保存しますか? – Hank

+1

要素が以前のコンテナから再作成または再利用され、一部のプロパティがtrueまたはVisibleに設定されているため、詳細が表示されます。しかし、これはあなたを助けません。 – mm8

関連する問題