2017-09-11 50 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