Ir para o conteúdo
Optimizing Infragistics XamDataGrid Performance

Optimizing Infragistics XamDataGrid Performance

O componente XamDataGrid, um dos controles no produto NetAdvantage for WPF Line of Business (versão de avaliação gratuita disponível aqui) é o componente usado com mais frequência do nosso produto WPF. Ele apresenta seus dados tabulares e permite agrupar, classificar, filtrar, calcular resumos de colunas, bem como controlar seu layout por agrupamento de colunas, reordenação, fixação e muito mais.

10min read

O componente XamDataGrid, um dos controles no produto NetAdvantage for WPF Line of Business (versão de avaliação gratuita disponível aqui) é o componente usado com mais frequência do nosso produto WPF. Ele apresenta seus dados tabulares e permite agrupar, classificar, filtrar, calcular resumos de colunas, bem como controlar seu layout por agrupamento de colunas, reordenação, fixação e muito mais.

O XamDataGrid também é capaz de lidar com atualizações de dados em tempo real e grandes volumes de dados com eficiência. Nesses cenários, o desempenho do XamDataGrid é fundamental para a usabilidade do aplicativo. É por isso que, neste post, veremos o que você pode fazer para maximizar seu desempenho.

Built-In Optimizations

O XamDataGrid usa uma variedade de métodos internamente para garantir que você esteja obtendo o melhor desempenho – ele reutiliza elementos do apresentador no nível do registro e da célula, armazena em cache as informações de estilo, usa rolagem de dica de ferramenta adiada e criação lenta de objetos. Estão disponíveis informações mais específicas sobre otimizações de desempenho. No entanto, todas essas otimizações já foram incorporadas ao controle e são prontas para uso sem nenhum custo.

Então, quais são as maneiras de melhorar o desempenho? Reuni uma lista de pontos que você pode considerar usar, a maioria dos quais é implementada no projeto de exemplo. Tentei fornecer o máximo de informações sobre como essas estratégias afetam a aparência ou o comportamento do seu aplicativo, para que você possa considerar os requisitos específicos do seu cenário e tomar uma decisão informada sobre quais usar.

Associação a valores pré-formatados

Uma maneira de melhorar o desempenho em colunas somente leitura é reduzir a formatação de valor. Muitas vezes, a formatação de valor é implementada usando conversores, porque é uma maneira fácil e limpa de encapsular a lógica de formatação. No entanto, ao rolar, a grade faz com que a lógica do conversor seja invocada cada vez que uma célula é exibida – ao rolar horizontalmente para exibir uma nova coluna, o conversor é invocado um número de vezes igual ao número de linhas visíveis. A sobrecarga desse processamento é aumentada ao usar atualizações em tempo real. Uma maneira de reduzir a carga é executar a formatação de valor no código e vincular a grade ao resultado formatado, que é calculado apenas uma vez. Além disso, usando uma abordagem preguiçosa, um valor pode ser formatado uma vez e depois armazenado em cache, essencialmente removendo qualquer necessidade de formatação a ser acionada pela interface do usuário.

Digamos que você tenha um objeto de negócios Produto com um valor de Preço que gostaria de formatar de uma maneira específica. Uma maneira de fazer isso é estender o Product original usando um FormattedProduct, que adiciona uma propriedade PriceFormatted, que é calculada quando é solicitada e armazenada para solicitações posteriores. Se houver um número relativamente pequeno de valores exclusivos, uma maneira de reduzir ainda mais o requisito de espaço dessa abordagem de cache é usar um dicionário para valores formatados.

Em seguida, depois de associar a uma lista desses FormattedProducts, você precisa impedir que a coluna Price seja mostrada e alterar o cabeçalho da coluna PriceFormatted, que mostrará seus valores formatados. Você pode fazer isso no manipulador de eventos do evento FieldLayoutInitialized, onde você pode definir a Visibilidade da coluna Price como Collapsed e a propriedade Label do PriceFormatted como 'Price'.

Estilização

Estilos sem pairar

Um aumento substancial de desempenho pode ser alcançado definindo um estilo que se abstenha de aplicar cores e efeitos nos elementos visuais usados com mais frequência. Um exemplo é não definir nenhuma coloração para a linha que está sendo pairada. Faça download do estilo sem mouse XamDataGrid de alto desempenho. Claro, você pode querer continuar usando algumas dessas propriedades de estilo e modificá-las para atender às suas necessidades. Adicione esse arquivo ao seu projeto e referencie-o no XamDataGrid da seguinte maneira:

<igDP:XamDataGrid.Resources>
   <ResourceDictionary Source="HoverlessStyles.xaml" />
</igDP:XamDataGrid.Resources>

Minimalist Styles

Ao definir seus próprios modelos para elementos que aparecem muitas vezes na hierarquia visual, como CellValuePresenters, tente usar o mínimo de elementos possível. Um modelo será inicializado para todos os CellValuePresenters em exibição, o que pode fazer com que o número total de elementos visuais aumente rapidamente, tendo um efeito adverso no desempenho. Uma explicação mais detalhada sobre o impacto dos estilos no desempenho está disponível. O CellValuePresenter mínimo consiste em uma Border que inclui um TextBlock. Um detalhe importante necessário para melhorar o desempenho ao usar o estilo minimalista é definir a propriedade ForceCellVirtualization (nova na versão 11.1) como true. Adicione esse arquivo de estilo minimalista ao seu projeto e referencie-o no XamDataGrid da seguinte maneira:

<igDP:XamDataGrid.Resources>
   <ResourceDictionary Source="ReadOnlyHighPerformanceStyle.xaml" />
</igDP:XamDataGrid.Resources>

Efeito da contenção de controles no desempenho do XamDataGrid

Evite usar efeitos de bitmap em controles que contêm o XamDataGrid ou em elementos XamDataGrid. Por mais atraentes que sejam, esses efeitos têm um custo de desempenho significativo.

Se você colocar o XamDataGrid em um controle StackPanel, ele terá uma região de tamanho infinito para exibir seus registros, o que fará com que ele renderize CellValuePresenters para todas as células. Embora a rolagem possa ser tratada corretamente pelo StackPanel delimitador, o volume de memória devido ao grande número de apresentadores será significativo.

Temas

Há uma certa sobrecarga envolvida na determinação dos modelos a serem usados para vários elementos. Você pode obter um benefício de desempenho definindo o tema a ser usado, mesmo que seja o tema Aero padrão, conforme mostrado abaixo:

<igDP:XamDataGrid Theme="Aero" />

Atualizando o FieldCollection

Se você estiver adicionando ou removendo campos da coleção Fields de um FieldLayout com elementos visíveis no apresentador de dados, isso poderá afetar negativamente o desempenho. Ao fazer várias alterações na coleção, sempre chame BeginUpdate antes dessas alterações e EndUpdate após as alterações.

Eventos suprimidos

Outra maneira pela qual os desenvolvedores podem melhorar o desempenho é suprimindo eventos roteados que eles sabem que não serão manipulados. Isso melhora o desempenho devido à sobrecarga incorrida com eventos roteados em hierarquias de elementos. Também há eventos CLR diretos adicionados para eventos roteados comuns no DataPresenterBase. Eles são nomeados com o nome do evento roteado seguido por "Direct", como "CellActivatedDirect", no caso do evento roteado "CellActivated". Isso permite que você suprima o evento roteado e ainda manipule seu equivalente direto.

Para suprimir eventos, adicione-os à coleção DataPresenterBase.SuppressedEvents, conforme implementado no projeto de exemplo e também mostrado abaixo:

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:igDP="http://infragistics.com/DataPresenter"
    xmlns:igED="http://infragistics.com/Editors"
    Title="Window1" Height="600" Width="800">
    <Grid>
        <igDP:XamDataGrid>
            <igDP:XamDataGrid.SuppressedEvents>
                <igDP:RoutedEventWrapper RoutedEvent="igED:ValueEditor.TextChanged" />

…
                <igDP:RoutedEventWrapper RoutedEvent="igED:ValueEditor.ValueChanged" />
            </igDP:XamDataGrid.SuppressedEvents>
        </igDP:XamDataGrid>
    </Grid>
</Window>

Modo de dimensionamento de registro

A propriedade de modo FieldLayoutSettings.DataRecordSizing controla a maneira como os registros no XamDataGrid são dimensionados e redimensionados. Essa propriedade tem um efeito no desempenho porque controla se cada linha é dimensionada separadamente ou se as linhas são de altura igual.

Os valores Fixed e SizableSynchronized para essa propriedade resultam em linhas de igual altura. Essas duas configurações oferecem a maior vantagem de desempenho, pois o XamDataGrid pode fazer o layout de linhas de altura equivalente mais rapidamente do que linhas de altura diferente, que exigem recursos adicionais durante a operação de layout.

Os valores SizedToContentAndFixed e SizedToContentAndIndividuallySizable para o FieldLayoutSettings.DataRecordSizing podem resultar em linhas de tamanho diferente. Embora essas configurações ofereçam uma certa flexibilidade no layout, elas exigem recursos adicionais no layout, tendo um impacto negativo no desempenho do XamDataGrid durante a rolagem.

Setting Scrolling Mode

O comportamento de rolagem de polegar padrão do XamDataGrid é a rolagem adiada com uma dica de ferramenta que contém o valor da coluna (que você pode especificar usando a propriedade IsScrollTipField) para o registro que será exibido. Isso permite que você localize rapidamente o registro que está procurando usando seu valor em uma coluna específica, em vez de pausar a rolagem para procurar o valor da coluna de registro atual.

Você pode habilitar a rolagem imediata definindo a propriedade ScrollingMode como Immediate. Ao contrário da rolagem adiada, a rolagem imediata requer que os registros na posição de rolagem correspondente sejam mostrados em sua totalidade. Essa abordagem resulta na manipulação de muitos elementos visuais em rápida sucessão, impactando negativamente o desempenho. Por isso, evite usar o modo de rolagem imediata o máximo possível, a menos que você tenha um requisito específico para fazê-lo.

Adjusting Cell Presenter Virtualization

Você pode controlar como o XamDataGrid virtualiza seus apresentadores de registro e célula, definindo as propriedades RecordContainerGenerationMode e CellContainerGenerationMode . Examinaremos as diferentes estratégias de virtualização, suas implicações de espaço e tempo e os cenários para os quais são úteis.

Reciclar

Por padrão, o XamDataGrid recicla os apresentadores que usa – ele inicializa apenas os apresentadores para os registros/células visíveis que são reutilizados à medida que a exibição é rolada. Esse modo de cache é otimizado para navegação geral de dados, minimizando o volume de memória, às custas do aspecto do tempo. Embora essa abordagem economize memória e funcione bem na maioria dos casos, ela pode resultar em uma rolagem menos do que perfeita, especialmente com editores como XamDateTimeEditor contendo uma hierarquia de elementos complexa.

PreLoad

Vamos imaginar um cenário em que você tem muitas colunas com editores complexos, como XamDateTimeEditors, e precisa de rolagem horizontal rápida para exibir colunas extras. Usando a estratégia PreLoad, o XamDataGrid inicializa apresentadores para todas as células a serem mostradas, garantindo uma experiência de rolagem suave, ao custo de um maior tempo de carregamento inicial e volume de memória. A configuração PreLoad é apropriada para cenários em que você tem um número relativamente pequeno de linhas (ao definir RecordContainerGenerationMode) ou colunas (ao definir CellContainerGenerationMode), caso contrário, o tempo de carregamento e o volume de memória podem se tornar perceptíveis.

LazyLoad

Você pode estar implementando um cenário em que tem uma quantidade relativamente pequena de registros e uma grande quantidade de colunas, e o usuário nem sempre examina todas as colunas. Nesse caso, você pode minimizar o volume de memória e, ao mesmo tempo, garantir uma boa velocidade de rolagem para colunas que já foram exibidas, inicializando os apresentadores das colunas apenas uma vez – quando elas são exibidas e armazenando-as em cache para melhorar a rolagem quando elas são exibidas pela segunda vez. Isso resulta em um pequeno tempo de carregamento inicial, um volume de memória contendo apresentadores para todas as células que foram exibidas desde o carregamento do XamDataGrid (não todas, como no caso da estratégia PreLoad) e uma penalidade de desempenho de rolagem apenas na primeira vez que uma célula é exibida. Trazer as mesmas células à exibição uma segunda vez será rápido, pois seus apresentadores teriam sido armazenados em cache na primeira vez que foram mostrados.

Hierarchies

Para melhorar o desempenho, o XamDataGrid, por padrão, usa um único painel para exibir registros pai e filho. Isso tem as seguintes desvantagens:

  • Os registros aninhados não são cercados por cromo
  • Os gatilhos no modelo de um objeto RecordPresenter que lidam com registros aninhados serão ignorados
  • A animação no modelo de um objeto RecordPresenter que lida com registros aninhados será ignorada

Se você quiser usar qualquer um dos recursos listados acima, poderá usar vários painéis aninhados definindo a propriedade UseNestedPanels do GridViewSettings como true. Informações adicionais sobre registros hierárquicos e desempenho estão disponíveis.

Resumo

Nesta postagem do blog, examinamos várias maneiras de ajustar o desempenho do XamDataGrid. Considere e use-os na próxima vez que estiver criando seu aplicativo, tendo em mente seus requisitos de temas, estilo, bem como suas restrições de memória e tempo.

Solicite uma demonstração