2011-12-01 20 views
9

Estoy usando la cuadrícula de datos wpf para visualizar grandes cantidades de datos (alrededor de 100 columnas y 1000 filas). Las columnas están vinculadas a propiedades añadidas dinámicamente utilizando typedescripter. De forma predeterminada, la cuadrícula de datos muestra toda la columna, sin embargo, hemos agregado una funcionalidad que permite al usuario ver solo un subconjunto de todas las columnas y también puede cambiar el orden de las columnas mostradas. Actualmente estoy logrando esto al alternar la propiedad de visibilidad de las columnas y cambiar su índice de visualización. Sin embargo, el rendimiento de hacerlo realmente apesta.Problemas de rendimiento en mover/ocultar columnas en la cuadrícula de datos de wpf grande

A continuación se muestra un ejemplo para reproducir el problema

El XAML parece bastante sencillo

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

El código subyacente es el siguiente

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

Este modelo de vista reproduce grande datos usando DataTable creado manualmente. Sin embargo en el código real detrás de cuadrícula de datos se une a la clase con propiedades dinámicas añadidas usando 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; 
     } 
    } 
} 

He intentado lo siguiente, pero sin suerte hasta ahora

1. El rendimiento es mejor si enciendo fila y columna de la virtualización . Sin embargo, esto arruina el rendimiento de desplazamiento que no es aceptable (especialmente si intenta arrastrar el pulgar).
2. En lugar de cambiar la visualización y la visibilidad, intenté eliminar todas las columnas y luego solo agregué las necesarias, pero tampoco modificó el rendimiento.

Realmente agradeceré cualquier ayuda con esto. No queremos ganancias de rendimiento a expensas de un rendimiento de desplazamiento adverso. Entonces, si la virtualización debe activarse, ¿cómo podemos mejorar el rendimiento del desplazamiento? O hay alguna forma mejor de lograr tanto un buen rendimiento de desplazamiento como un buen rendimiento de la columna show/hide/move con tan grandes datagrids.

+1

¿Quién verá 1000 filas al mismo tiempo? Al menos 25-100 por página ... Debe reducir la cantidad de filas y su problema desaparecerá. –

+0

Gracias por su sugerencia. También tenemos una opción para paginar filas, pero el diseño comercial también requiere una opción que permita al usuario ver y comparar todas las filas juntas (la ventana a menudo se extiende a través de dos monitores para que puedan ver muchas filas) – shomat

+0

Tengo el mismo problema, ¿Has encontrado alguna solución? –

Respuesta

1

Realmente debe dejar la virtualización activada cuando utilice conjuntos de datos más grandes, de lo contrario, cada celda pasará por el pase de diseño/medida, incluso si no se representa en la pantalla. Tuve cierto éxito al usar ScrollViewer.IsDeferredScrollingEnabled = "False" para ajustar el comportamiento de desplazamiento, pero en general, no he tenido mucha suerte con el rendimiento con grandes conjuntos de datos en la cuadrícula de datos de WPF.

+0

Gracias por su respuesta. Sí, estoy de acuerdo en que la virtualización debe activarse para grandes cuadrículas de datos (o la huella de memoria es demasiado alta). Todo se reduce a mejorar el rendimiento del desplazamiento con la virtualización activada. He jugado con desplazamiento diferido. Creo que solo cambia la experiencia de UI. El problema de rendimiento aparecerá cada vez que la red necesite ser repintada en cualquier caso. Todavía estamos tratando de encontrar una salida al desplazamiento del desorden del rendimiento – shomat

+0

Si puede resolver algo, actualice. Hemos estado lidiando con escenarios similares desde hace un tiempo también. ¡Gracias! – GlitterMonkey

Cuestiones relacionadas