Otimizando o desempenho: vinculação de dados
A vinculação de dados do Windows Presentation Foundation (WPF) fornece uma maneira simples e consistente para os aplicativos apresentarem e interagirem com 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 fornece 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 vinculaçã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 o Microsoft .NET Framework reflection ou um ICustomTypeDescriptor. Aqui estão três métodos para resolver referências de objeto para vinculação.
O primeiro método envolve o uso da reflexão. Nesse caso, o objeto PropertyInfo é usado para descobrir os atributos da propriedade e fornece acesso aos metadados da propriedade. Ao usar a interface ICustomTypeDescriptor, o mecanismo de vinculação de dados usa essa interface para acessar os valores de propriedade. A interface ICustomTypeDescriptor é 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 interface INotifyPropertyChanged 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 INotifyPropertyChanged.
Se o objeto de origem for um objeto CLR e a propriedade de origem for uma propriedade CLR, o motor de ligação de dados do Windows Presentation Foundation (WPF) deverá primeiro usar a reflexão no objeto de origem para obter o TypeDescriptore, em seguida, consultar um PropertyDescriptor. Esta sequência de operações de reflexão é potencialmente muito demorada do ponto de vista do 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 source que é uma propriedade CLR. Nesse caso, o mecanismo de vinculação de dados usa a reflexão diretamente no tipo de origem e obtém a propriedade necessária. Este 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 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 juntos resolvem a referência de propriedade independentemente. Este é o método ideal para resolver referências de objeto usadas para vinculação de dados.
A tabela abaixo compara a velocidade de associação de dados à propriedade Text de mil elementos TextBlock utilizando estes três métodos.
Associar a propriedade Text de um TextBlock | Tempo de vinculação (ms) | Tempo de renderização -- inclui vinculaçã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 de grande dimensão
Há um impacto significativo no desempenho quando os dados são vinculados 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 1000 objetos TextBlock | Tempo de vinculação (ms) | Tempo de renderização -- inclui vinculação (ms) |
---|---|---|
Para um objeto CLR com 1000 propriedades | 950 | 1200 |
Para 1000 objetos CLR com uma propriedade | 115 | 314 |
Vinculação a um ItemsSource
Considere um cenário em que tenhas um objeto CLR List<T> que contém uma lista de funcionários que pretendes exibir num ListBox. Para criar uma correspondência entre esses dois objetos, você vincularia sua lista de funcionários à propriedade ItemsSource do ListBox. No entanto, suponha que você tenha um novo funcionário se juntando ao seu grupo. Você pode pensar que, para inserir essa nova pessoa em seus valores de ListBox vinculados, você simplesmente adicionaria essa pessoa à sua lista de funcionários e esperaria que essa alteração fosse reconhecida pelo mecanismo de vinculação de dados automaticamente. Esta suposição revelar-se-ia falsa; Na verdade, a mudança não será refletida no ListBox automaticamente. Isso ocorre porque o objeto CLR List<T> não gera automaticamente um evento de alteração de coleção. Para que o ListBox adote as alterações, terias que recriar a tua lista de funcionários e anexá-la novamente à propriedade ItemsSource do ListBox. Embora esta solução funcione, introduz um enorme impacto no desempenho. Cada vez que você reatribui o ItemsSource de ListBox a um novo objeto, o ListBox primeiro joga fora seus itens anteriores e regenera toda a sua lista. O impacto no desempenho é intensificado se o seu ListBox for mapeado para um DataTemplatecomplexo.
Uma solução muito eficiente para este problema é tornar a sua lista de funcionários uma ObservableCollection<T>. Um objeto ObservableCollection<T> 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 toda a lista.
A tabela abaixo 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á vinculado ao ItemsSourcedo elemento ListBox. O número na segunda linha representa o tempo decorrido quando um ObservableCollection<T> está vinculado ao ItemsSourcedo elemento ListBox . Observe a economia de tempo significativa usando a estratégia de vinculação de dados ObservableCollection<T>.
Ligação de dados do ItemsSource | Tempo de atualização para 1 item (ms) |
---|---|
Para um CLR objeto List<T> | 1656 |
Para um ObservableCollection<T> | 20 |
Vincular IList ao ItemsControl e não ao IEnumerable
Se você tiver a opção entre vincular um IList<T> ou um IEnumerable a um objeto ItemsControl, escolha o objeto IList<T>. A vinculação de IEnumerable a um ItemsControl força o WPF a criar um objeto envoltório IList<T>, o que significa que o 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ê 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.
Ver também
- Otimizando o desempenho do aplicativo WPF
- Planejando o desempenho de aplicativos
- Tirar partido do hardware
- Layout e Design
- Gráficos e Imagens 2D
- Comportamento do objeto
- Recursos do Aplicativo
- Text
- Outras recomendações de desempenho
- Visão Geral da Vinculação de Dados
- Passo a passo: Armazenando dados de aplicativo em cache em um aplicativo WPF
.NET Desktop feedback