Rendimiento de la cuadrícula de datos WPF
performance datagrid (6)
¿Por casualidad tiene una tableta de cualquier tipo instalada (a través de USB o una tableta PC)?
Encontré un error de rendimiento en la cuadrícula de datos de WPF cuando uso una tableta. Publiqué un video y es reconocido por MS aquí en este hilo
Saludos, Jon
Estoy trabajando con la cuadrícula de datos de WPF Toolkit y está desplazándose extremadamente lento en este momento. La grilla tiene 84 columnas y 805 filas. (Incluye 3 columnas fijas y el encabezado está fijo.) El desplazamiento horizontal y vertical es extremadamente lento. La virtualización está activada y he habilitado la virtualización de columnas y la virtualización de filas explícitamente en el xaml. ¿Hay algo de qué preocuparse que realmente pueda afectar el rendimiento, como los métodos de enlace, o qué xaml hay en cada plantilla de celda?
Una cosa a tener en cuenta es que estoy agregando dinámicamente las columnas en la creación de la cuadrícula de datos. ¿Podría estar afectando algo? (También creo dinámicamente el celltemplate al mismo tiempo para que mis enlaces se configuren correctamente).
A continuación se muestra el código de la plantilla para la mayoría de las celdas que se generan. Básicamente para las columnas que necesito agregar dinámicamente (que es la mayoría de ellas), recorro mi lista y agrego las columnas usando el método AddColumn, además construyo dinámicamente la plantilla para que las declaraciones vinculantes indexen correctamente el elemento correcto en la colección para esa columna. La plantilla no es demasiado compleja, solo dos TextBlocks, pero yo vinculo cuatro propiedades diferentes en cada uno. Parece que pude exprimir un poco más de rendimiento al cambiar los enlaces a OneWay:
private void AddColumn(string s, int index)
{
DataGridTemplateColumn column = new DataGridTemplateColumn();
column.Header = s;
//Set template for inner cell''s two rectangles
column.CellTemplate = CreateFactViewModelTemplate(index);
//Set Style for header, ie rotate 90 degrees
column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
column.Width = DataGridLength.Auto;
dgMatrix.Columns.Add(column);
}
//this method builds the template for each column in order to properly bind the rectangles to their color
private static DataTemplate CreateFactViewModelTemplate(int index)
{
string xamlTemplateFormat =
@"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay}"" />
<TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay}"" />
</Grid>
</DataTemplate>";
string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());
return (DataTemplate)XamlReader.Parse(xamlTemplate);
}
Como no puedo ver tu código fuente, es bastante difícil ayudarte. Especialmente porque el rendimiento de una aplicación WPF está influenciado por muchas cosas. Para obtener algunos consejos sobre qué buscar, consulte Optimizar el rendimiento de la aplicación WPF . Y sí, importa mucho qué xaml se use en cada celda. Porque generalmente los problemas de rendimiento se reducen a "demasiados elementos". ¿Sabías que un TextBox creo que son 30 elementos individuales? Recomiendo que utilice las herramientas de generación de perfiles de rendimiento para WPF para obtener más información sobre su problema específico. Intente minimizar la cantidad de elementos que está utilizando (por ejemplo, cambiando de TextBox a TextBlock cuando corresponda).
También debe verificar si existen problemas de rendimiento en cualquier PC en la que pruebe la aplicación. Tal vez la PC que está usando está forzando a WPF a un renderizado basado en software. ¿O está utilizando algún BitmapEffects?
Editar:
Mirando tu código, te sugiero que cambies
column.Width = DataGridLength.Auto;
a un ancho fijo razonable, ya que la cuadrícula de datos no tiene que volver a calcular el ancho de forma dinámica cada vez que algo cambia (como agregar filas o incluso desplazarse).
Tuve un caso en el que mi objeto subyacente tenía propiedad solo con setter. Se puede acceder a la misma propiedad implementando ITypedList en la colección y a través de TypeDescriptionProvider / ICustomTypeDescriptor en los objetos individuales. Eliminar la propiedad o agregar un getter resolvió los problemas de rendimiento.
Un consejo general para los problemas de rendimiento de DataGrid: tuve un problema con DataGrid en el que tardé literalmente unos segundos en actualizar después de cambiar el tamaño de una ventana, ordenar columnas, etc. y bloqueé la interfaz de usuario de la ventana mientras lo hacía (1000 filas, 5 columnas )
Todo se redujo a un problema (¿error?) Con los cálculos de tamaño de WPF. Lo tenía en una grilla con RowDefinition Height = "Auto", lo que causaba que el sistema de renderizado intentara recalcular el tamaño de DataGrid en tiempo de ejecución midiendo el tamaño de cada columna y fila, presumiblemente al llenar toda la grilla ( como yo lo entiendo). Se supone que debe manejar esto inteligentemente de alguna manera, pero en este caso no fue así.
Una comprobación rápida para ver si se trata de un problema relacionado es establecer las propiedades de Altura y Ancho de DataGrid en un tamaño fijo durante la prueba e intentar ejecutarlo nuevamente. Si su rendimiento se restablece, una solución permanente puede estar entre estas opciones:
- Cambie los tamaños de los elementos que contienen para ser relativos (*) o valores fijos
- Establezca MaxHeight y MaxWidth de DataGrid en un valor fijo mayor de lo que podría obtener en el uso normal
- Pruebe otro tipo de contenedor con una estrategia de cambio de tamaño diferente (Grid, DockPanel, etc.)
Una cosa que sugeriría en tales escenarios es ver cómo ha aplicado el estilo y cuál es el estilo en cada celda. El estilo aplicado si tiene un árbol visual complejo tiende a degradar el rendimiento.
También puede probar la opción de desplazamiento diferido en la última cuadrícula de datos de WPF.
en uno de mis proyectos, la siguiente configuración de estilo de cuadrícula estaba causando un problema importante de rendimiento:
<Style TargetType=''{x:Type controls:DataGrid}''>
<Setter Property=''ScrollViewer.CanContentScroll'' Value=''False'' />
...
Cuando eliminé la configuración ScrollViewer.CanContentScroll, el problema de rendimiento desapareció.