Otimizando desempenho: vinculaçã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 vinculados a dados de uma variedade de fontes de dados na forma de objetos CLR e XML.

Este tópico apresenta recomendações de desempenho de vinculação de dados.

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

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

A origem de uma associação de dados do Windows Presentation Foundation (WPF) pode ser qualquer objeto CLR. Você pode vincular a propriedades, subpropriedades 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 ICustomTypeDescriptorarquivo . 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 PropertyInfo objeto é usado para descobrir os atributos da propriedade e fornece acesso aos metadados da propriedade. Ao usar a ICustomTypeDescriptor interface, o mecanismo de vinculação de dados usa essa interface para acessar os valores de propriedade. A ICustomTypeDescriptor interface é especialmente útil nos 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 INotifyPropertyChanged interface ou usando as notificações de alteração associadas ao TypeDescriptor. No entanto, a estratégia preferida para implementar notificações de alteração de propriedade é usar INotifyPropertyChangedo .

Se o objeto de origem for um objeto CLR e a propriedade source for uma propriedade CLR, o mecanismo de vinculação de dados do Windows Presentation Foundation (WPF) precisará primeiro usar a reflexão no objeto de origem para obter o TypeDescriptor, e, em seguida, consultar um PropertyDescriptorarquivo . 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 INotifyPropertyChanged interface e uma propriedade source que é uma propriedade CLR. Nesse caso, o mecanismo de vinculação de dados usa reflexão diretamente no tipo de fonte e obtém a propriedade necessária. Este ainda não é o melhor método, mas ele custará menos nos requisitos de conjunto de trabalho do que o primeiro método.

O terceiro método para resolver referências de objeto envolve um objeto source que é um e uma propriedade source que é um DependencyObjectDependencyPropertyarquivo . Nesse caso, o mecanismo de vinculação de dados não precisa usar reflexão. Em vez disso, o mecanismo de propriedade e o mecanismo de vinculação de dados resolvem juntos a referência da propriedade independentemente. Esse é o melhor método para resolver referências de objeto usadas para vinculação de dados.

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

Associando a propriedade Text de um TextBlock Tempo de associaçã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
A um de um DependencyPropertyDependencyObject. 90 263

Associando a objetos CLR grandes

Há um impacto significativo no desempenho quando os dados se vinculam 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 vinculação e renderização para vinculação de dados a um único objeto CLR grande versus vários objetos menores.

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

Associando a um ItemsSource

Considere um cenário no qual você tenha um objeto CLR List<T> que contém uma lista de funcionários que você deseja exibir em um ListBoxarquivo . Para criar uma correspondência entre esses dois objetos, você vincularia sua lista de funcionários à ItemsSource propriedade 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 vinculados, você simplesmente adicionaria essa pessoa à sua lista de funcionários e esperaria que essa alteração fosse reconhecida pelo mecanismo de vinculação ListBox de dados automaticamente. Essa suposição se revelaria falsa; na realidade, a alteração não será refletida ListBox no automático. Isso ocorre porque o objeto CLR List<T> não gera automaticamente um evento changed de coleção. Para obter o ListBox para pegar as alterações, você teria que recriar sua lista de funcionários e anexá-la novamente à ItemsSource propriedade do ListBox. Embora essa solução funcione, ela ocasiona um grande impacto no desempenho. Cada vez que você reatribui o de ListBox a um novo objeto, o primeiro joga fora seus itens anteriores e regenera toda a ItemsSourceListBox sua lista. O impacto no desempenho é ampliado se os mapas ListBox forem mapeados para um complexo DataTemplate.

Uma solução muito eficiente para esse problema é fazer com que sua lista de funcionários seja feita com um ObservableCollection<T>. Um ObservableCollection<T> objeto gera uma notificação de alteração que o mecanismo de vinculaçã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 abaixo mostra o tempo necessário para atualizar o (com a virtualização da ListBox 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> é vinculado ao ListBox elemento ItemsSource. O número na segunda linha representa o tempo decorrido quando um ObservableCollection<T> é vinculado ao ListBox .ItemsSource Observe a economia de tempo significativa usando a estratégia de vinculação de ObservableCollection<T> dados.

Vinculação de dados de ItemsSource Atualizar tempo para 1 item (ms)
Para um objeto CLR List<T> 1656
Para um ObservableCollection<T> 20

Associar IList a ItemsControl não IEnumerable

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

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

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

Confira também