Compartilhar via


Otimizando o desempenho: associação de dados

A associação de dados do WPF (Windows Presentation Foundation) fornece uma maneira simples e consistente para os aplicativos apresentarem e interagirem com os dados. Os elementos podem ser associados a dados de uma variedade de fontes de dados na forma de objetos CLR e XML.

Este tópico fornece recomendações de desempenho de associação de dados.

Como as referências de associação de dados são resolvidas

Antes de discutir problemas de desempenho de associação de dados, vale a pena explorar como o mecanismo de associação de dados do WPF (Windows Presentation Foundation) resolve referências de objeto para associação.

A origem de uma associação de dados do WPF (Windows Presentation Foundation) pode ser qualquer objeto CLR. Você pode vincular a propriedades, sub-propriedades ou indexadores de um objeto CLR. As referências de associação são resolvidas usando uma reflexão do Microsoft .NET Framework ou um ICustomTypeDescriptor. Aqui estão três métodos para resolver referências de objeto para associação.

O primeiro método envolve o uso de reflexão. Nesse caso, o objeto PropertyInfo é usado para descobrir os atributos da propriedade e fornece acesso aos metadados de propriedade. Ao usar a interface ICustomTypeDescriptor, o mecanismo de associação de dados usa essa interface para acessar os valores da propriedade. A interface ICustomTypeDescriptor é especialmente útil em casos em que o objeto não tem um conjunto estático de propriedades.

As notificações de alteração de propriedade podem ser fornecidas implementando a interface INotifyPropertyChanged ou usando as notificações de alteração associadas ao TypeDescriptor. No entanto, a estratégia preferencial para implementar notificações de alteração de propriedade é usar INotifyPropertyChanged.

Se o objeto de origem for um objeto CLR e a propriedade de origem for uma propriedade CLR, o mecanismo de associação de dados do WPF (Windows Presentation Foundation) deverá primeiro usar a reflexão sobre o objeto de origem para obter o TypeDescriptore, em seguida, consultar um PropertyDescriptor. Essa sequência de operações de reflexão é potencialmente muito demorada de uma perspectiva de desempenho.

O segundo método para resolver referências de objeto envolve um objeto de origem CLR que implementa a interface INotifyPropertyChanged e uma propriedade de origem que é uma propriedade CLR. Nesse caso, o mecanismo de associação de dados usa reflexão diretamente sobre o tipo de origem e obtém a propriedade necessária. Esse ainda não é o método ideal, mas custará menos em requisitos de conjunto de trabalho do que o primeiro método.

O terceiro método para resolver referências de objeto envolve um objeto de origem que é um DependencyObject e uma propriedade de origem que é um DependencyProperty. Nesse caso, o mecanismo de associação de dados não precisa usar reflexão. Em vez disso, o mecanismo de propriedade e o mecanismo de associação de dados juntos resolvem a referência de propriedade de forma independente. Esse é o método ideal para resolver referências de objeto usadas para associação de dados.

A tabela a seguir compara a velocidade da associação de dados à propriedade Text de mil elementos TextBlock usando esses três métodos.

Vincular a propriedade Text de um TextBlock Tempo de Ligação (ms) Tempo de renderização – inclui associação (ms)
Para uma propriedade de um objeto CLR 115 314
Para uma propriedade de um objeto CLR que implementa INotifyPropertyChanged 115 305
Para um DependencyProperty de um DependencyObject. 90 263

Vinculação a objetos CLR grandes

Há um impacto significativo no desempenho ao associar dados a um único objeto CLR com milhares de propriedades. Você pode minimizar esse impacto dividindo o único objeto em vários objetos CLR com menos propriedades. A tabela mostra os tempos de associação e renderização para associação de dados a um único objeto CLR grande versus vários objetos menores.

Associação de dados de 1000 objetos TextBlock tempo de vinculação (ms) Tempo de renderização – inclui associação (ms)
Para um objeto CLR com 1000 propriedades 950 1200
Para 1000 objetos CLR com uma propriedade 115 314

Associação de um Fonte de Itens

Considere um cenário no qual você tem um objeto CLR List<T> que contém uma lista de funcionários que você deseja exibir em um ListBox. Para criar uma correspondência entre esses dois objetos, você associaria sua lista de funcionários à propriedade ItemsSource do ListBox. No entanto, suponha que você tenha um novo funcionário ingressando em seu grupo. Você pode pensar que, para inserir essa nova pessoa em seus valores de ListBox associados, basta adicionar essa pessoa à sua lista de funcionários e esperar que essa alteração seja reconhecida automaticamente pelo mecanismo de associação de dados. Essa suposição seria falsa; na verdade, a alteração não será refletida no ListBox automaticamente. Isso ocorre porque o objeto clr List<T> não gera automaticamente um evento alterado de coleção. Para que o ListBox reconheça as alterações, você precisará recriar sua lista de funcionários e anexá-la novamente à propriedade ItemsSource do ListBox. Embora essa solução funcione, ela apresenta um enorme impacto no desempenho. Cada vez que você reatribui o ItemsSource de ListBox para um novo objeto, o ListBox primeiro joga fora seus itens anteriores e regenera toda a sua lista. O impacto no desempenho é ampliado se o ListBox for mapeado para um DataTemplatecomplexo.

Uma solução muito eficiente para esse problema é tornar sua lista de funcionários uma ObservableCollection<T>. Um objeto ObservableCollection<T> gera uma notificação de alteração que o mecanismo de associação de dados pode receber. O evento adiciona ou remove um item de um ItemsControl sem a necessidade de regenerar a lista inteira.

A tabela a seguir mostra o tempo necessário para atualizar o ListBox (com a virtualização da interface do usuário desativada) quando um item é adicionado. O número na primeira linha representa o tempo decorrido quando o objeto clr List<T> está associado ao ItemsSourcedo elemento ListBox . O número na segunda linha representa o tempo decorrido quando um ObservableCollection<T> está associado ao ItemsSourcedo elemento ListBox. Observe a economia de tempo significativa usando a estratégia de associação de dados ObservableCollection<T>.

Associação de dados à ItemsSource Tempo de atualização para 1 item (ms)
Para um objeto CLR List<T> 1656
Para um ObservableCollection<T> 20

Associar IList a ItemsControl, não a IEnumerable

Se você tiver uma opção entre associar um IList<T> ou um IEnumerable a um objeto ItemsControl, escolha o objeto IList<T>. Associar IEnumerable a um ItemsControl força o WPF a criar um objeto IList<T> wrapper, o que significa que seu desempenho é afetado pela sobrecarga desnecessária de um segundo objeto.

Não converta objetos CLR em XML apenas para vinculação de dados.

O WPF permite que você associe dados ao conteúdo XML; no entanto, a associação de dados ao conteúdo XML é mais lenta do que a associação de dados a objetos CLR. Não converta dados de objeto CLR em XML se a única finalidade for a associação de dados.

Consulte também