2011-12-01 67 views
9

我正在使用wpf datagrid顯示大量數據(大約100列和1000行)。這些列綁定到使用typedescripter動態添加的屬性。默認情況下,datagrid會顯示所有列,但我們添加的功能允許用戶僅查看所有列的子集,並且還可以更改顯示列的順序。我目前通過切換列的可見性屬性並更改其顯示索引來實現此目的。然而,這樣做的表現真的很糟糕。在大型wpf數據網格中移動/隱藏列的性能問題

下面是一個例子來重現問題

的XAML看起來很直截了當

<Window x:Class="WpfDataGridTestApplication.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    WindowState="Maximized"> 
<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"></RowDefinition> 
     <RowDefinition Height="*"></RowDefinition> 
    </Grid.RowDefinitions> 
    <StackPanel Grid.Row="0" Height="Auto" Margin="5"> 
     <CheckBox x:Name="ApplyColumns" Width="200" Margin="5" Checked="CheckBox_Checked" Unchecked="CheckBox_Checked">Show Predefined Columns</CheckBox> 
    </StackPanel> 
    <DataGrid 
     x:Name="Grid" EnableColumnVirtualization="False" 
     EnableRowVirtualization="False" 
     Grid.Row="1" SelectionUnit="Cell" 
     ItemsSource="{Binding MyDataView}"> 
    </DataGrid> 
</Grid> 

後面的代碼如下所示

public partial class MainWindow : Window 
{ 
    /// <summary> 
    /// this dictionary stores the column name of columns to display and their displayIndex 
    /// </summary> 
    Dictionary<string,int> _predefinedColumns=new Dictionary<string, int>() 
                { 
                 {"Column_8",0}, 
                 {"Column_9",1}, 
                 {"Column_11",2}, 
                 {"Column_14",3}, 
                 {"Column_12",4}, 
                 {"Column_34",5}, 
                 {"Column_78",6}, 
                 {"Column_54",7}, 
                 {"Column_88",8}, 
                 {"Column_98",9}, 
                 {"Column_90",10}, 
                 {"Column_51",11}, 
                 {"Column_100",12}, 
                 {"Column_35",13}, 
                 {"Column_112",14}, 
                 {"Column_101",15} 
                }; 
    public MainWindow() 
    { 
     InitializeComponent(); 
     DataContext = new MyClassViewModel(); 
    } 

    /// <summary> 
    /// Toggle display of only subset of columns 
    /// </summary> 
    /// <param name="sender"></param> 
    /// <param name="e"></param> 
    private void CheckBox_Checked(object sender, RoutedEventArgs e) 
    { 
     if (ApplyColumns.IsChecked ?? false) 
     { 
      foreach (var col in this.Grid.Columns) 
      { 
       if (_predefinedColumns.ContainsKey(col.Header as string)) 
       { 
        col.Visibility = Visibility.Visible; 
        col.DisplayIndex = _predefinedColumns[col.Header as string]; 
       } 
       else 
       { 
        col.Visibility = Visibility.Collapsed; 
       } 
      } 
     } 
     else 
     { 
      foreach (var col in this.Grid.Columns) 
      { 
       col.Visibility = Visibility.Visible; 
       var header = col.Header.ToString(); 
       col.DisplayIndex = Int32.Parse(header.Substring(7)) - 1; 
      } 
     } 
    } 
} 

此視圖模型再現大數據使用手動創建的DataTable。然而,在數據網格背後的實際代碼綁定與動態屬性類使用typedescripter

public class MyClassViewModel 
{ 
    public DataView MyDataView 
    { 
     get 
     { 
      var dt = new DataTable(); 
      foreach (var colNum in Enumerable.Range(1, 120)) 
      { 
       dt.Columns.Add(String.Format("Column_{0}", colNum), Type.GetType("System.Int32")); 
      } 

      var r = new Random(); 
      for (int x = 1; x <= 1000; x++) 
      { 
       var dr = dt.NewRow(); 
       foreach (var colNum in Enumerable.Range(1, 120)) 
       { 
        dr[String.Format("Column_{0}", colNum)] = r.Next(100); 
       } 
       dt.Rows.Add(dr); 
      } 
      return dt.DefaultView; 
     } 
    } 
} 

我曾嘗試以下,但到目前爲止

1.性能更好,如果我把行和列的虛擬化沒有運氣加入。但是,這會破壞不可接受的滾動性能(特別是如果您嘗試拖動拇指)。
2.除了更改顯示和可見性之外,我嘗試刪除所有列,然後僅添加所需的列,但它對性能也沒有影響。

我真的很感謝任何幫助。我們不希望以不利的滾動性能爲代價來提高性能。所以如果需要開啓虛擬化,我們應該如何改進滾動性能。或者有更好的方式來實現良好的滾動性能和良好的性能列顯示/隱藏/移動這樣大的數據網格。

+1

誰將在同一時間看到1000行?每頁至少25-100 ...你必須考慮減少行數量和問題消失。 –

+0

感謝您的建議。實際上,我們也可以選擇頁面行,但業務設計還需要一個選項,讓用戶可以查看並比較所有行(窗口通常橫跨兩個顯示器,以便可以看到很多行) – shomat

+0

我有同樣的問題,做過你發現任何解決方法? –

回答

1

當使用更大的數據集時,您應該保持虛擬化,否則即使未在屏幕上呈現,每個單元格都會通過佈局/度量傳遞。我已經通過使用ScrollViewer.IsDeferredScrollingEnabled =「False」來調整滾動行爲,但總的來說,在WPF數據網格中使用大數據集的性能方面沒有太大的成功。

+0

感謝您的回覆。是的,我同意虛擬化應該打開大型數據網格(或內存佔用太高)。這歸結於開啓虛擬化後提高滾動性能。我玩過延期滾動。我認爲這隻會改變UI體驗。無論何時需要重新繪製網格,性能問題都會顯示出來。我們仍試圖找出滾動性能混亂的一些方法 – shomat

+0

如果您能夠計算出任何內容,請更新。我們也一直在處理類似的情況。謝謝! – GlitterMonkey