Artigo do tipo Exemplos Práticos
Recursos especiais neste artigo:
Artigo no estilo Mentoring
Porque esse artigo é útil
Como se sabe, o papel principal de um controle em WPF é definir um comportamento. O WPF fornece controles que se adéquam a diversos comportamentos que são desejados em grande parte das aplicações. Porém, quando se quer um comportamento que não existe em nenhum controle natural do WPF e esse comportamento não pode ser atingido criando-se um User Control, a criação de um controle customizado faz-se necessária.

Este artigo trata da criação de Custom Controls em WPF – Windows Presentation Foundation. Como o próprio subtítulo sugere, são tratados todos os aspectos que envolvem a criação desses controles: como eles são e quando eles devem ser criados e utilizados, em quais aplicações e porque criar um controle novo se já existem diversos nativos no WPF, que podem, inclusive, serem compostos em um só para adquirir um comportamento diferente.

Criar um controle em WPF é ao mesmo interessante e desafiador. Porém, antes de começar a trabalhar com controles de WPF – Windows Presentation Foundation – é preciso entender a filosofia de design por trás do mesmo. É preciso entender porque as aplicações WPF funcionam da forma como funcionam e como as partes interagem umas com as outras para produzir a experiência para o usuário. Com esse entendimento, é possível construir controles e aplicações WPF mais confiáveis, robustas e que geram uma experiência muito melhor para o usuário das mesmas. Para isso, é importante perceber que o propósito de uma interface de usuário é coordenar entrada de dados e organizar o fluxo de trabalho, e os controles são os elementos visuais individuais que são agrupados logicamente com esse objetivo.

O que é necessário se ter em mente é que os controles em WPF são baseados no conceito de composição, ou seja, controles podem conter outros controles. Além disso, ele traz estilos, templates e triggers que aumentam ainda mais a capacidade de extensibilidade dos controles, e permitem ao desenvolvedor uma grande flexibilidade na hora de escrever aplicações WPF. Porém, existem momentos em que se faz necessária a criação de controles totalmente customizados, e WPF também fornece ferramentas que permitem essa criação.

Os controles em WPF possuem uma separação muito clara entre seu comportamento e seu visual. E o WPF permite que o desenvolvedor faça basicamente o que der vontade em cima do visual daquele controle, sem, entretanto, alterar o seu comportamento base. Como um exemplo, é possível alterar o formato de um botão para que ele seja redondo, quadrado, estrelar ou o que seja; porém, ele sempre vai estar sujeito a um evento de clique. É nesse ponto que os custom controls tornam-se importantes. Quando o desenvolvedor precisa de um comportamento que não está disponível em nenhum dos controles do WPF e não pode ser criado através de uma junção deles (UserControls) (BOX 1), será necessário escrever um controle customizado. O controle criado pode ser reutilizável, e para isso, é necessário que ele possua o mesmo tipo de flexibilidade que os controles nativos do WPF oferecem como suporte a estilos, templates e conteúdo rico.

BOX 1. CustomControls vs UserControls

As diferenças entre controles customizados e de usuário são um assunto que por si só poderia render um artigo completo. Eles possuem diversas diferenças que vão desde a criação até propriedades mais básicas, apesar de serem bastante similares.

Um controle de usuário é quase uma janela normal com code-behind. Trata-se de uma composição de controles existentes do WPF que são unidos em um grupo reutilizável. Consiste de um código XAML e um código com seu comportamento, que pode ser escrito em qualquer linguagem .NET. Um ponto importante a respeito dos UserControls é que eles não podem ser estilizados, ou seja, não oferecem suporte ao uso de ControlTemplates e Styles. Um bom exemplo, e bastante comum de ser utilizado, é um formulário de login de usuário, que consiste em uma composição de dois blocos de texto, duas caixas de texto e um botão.

Já um controle customizado será uma extensão da classe Control, direta ou indiretamente. Ele terá sua lógica em arquivo de código e sua aparência definida em um ControlTemplate que é parte de um estilo, definido em um arquivo separado. Além disso, eles podem ser estilizados como o desenvolvedor desejar. Eles são utilizados para criar comportamentos diferentes daqueles encontrados nos controles nativos do WPF. Um exemplo é a criação de uma caixa de texto que conterá a idade, e com isso, botões para aumentá-la e diminuí-la (spinner).

Filosofia de design do WPF

Antes de começar a falar em controles customizados, é preciso entender como funciona o WPF. O WPF foi criado com o objetivo de oferecer aos usuários uma experiência rica. Ele combina as interfaces de usuário, gráficos 2D e 3D, documentos e multimídia em um único framework. Além disso, ele utiliza um motor de renderização baseado em vetores, que tira vantagem dos hardwares gráficos modernos, tornando a interface de usuário mais rápida, eficiente e independente de resolução de tela.

Para auxiliar o desenvolvedor, o WPF cria uma separação muito clara entre a lógica de negócios da aplicação e sua interface gráfica. Isso faz com que haja uma independência do código com relação à tela e vice-versa. Essa independência gera uma série de benefícios durante as etapas de desenvolvimento, permitindo que os desenvolvedores foquem em desenvolver o comportamento da aplicação e os designers foquem em desenvolver a aparência da mesma. Além disso, isso contribui enormemente para a globalização da aplicação, uma vez que é possível vincular várias interfaces gráficas (uma em cada cultura) ao mesmo código.

O WPF utiliza uma noção muito correta, mas que normalmente os desenvolvedores não dão a devida atenção. Interfaces de usuário são feitas para representar dados e tomar decisões a respeito dos mesmos. Ou seja, quando o usuário olha para a aplicação, ele vê informações que são pertinentes para que uma determinada tarefa seja executada. Ou ainda, ele vê informação, significado e potencial para interação com essas informações, gerando um comportamento adequado. Já o desenvolvedor precisa enxergar é que o mais importante em uma aplicação não são os controles por si só, e sim o que os controles permitem que o usuário faça. Essa mudança de pensamento que o WPF propõe é capaz de criar as interfaces de usuário ricas, e não o WPF em si. O desenvolvedor precisa focar na experiência do usuário ao utilizar a aplicação. E as melhores experiências nesse caso são atingidas quando há uma perfeita harmonia entre os dados e o comportamento da aplicação.

A grande sacada da Microsoft com o WPF foi a forma de trabalhar com dados. Um controle responsável pela exibição de dados em WPF, inicialmente, pode exibir dados de qualquer tipo. Portanto, muitos desses controles assumem que o tipo padrão de dados a serem exibidos é System.Object. O WPF transforma esses dados quaisquer e os converte em algo visível, tangível e que aceita interações do usuário (BOX 2).

BOX 2. Trabalhando com dados em WPF

O WPF possui dois tipos de templates: Control e Data Templates. Um Control Template é usado quando o WPF quer a representação visual de um controle, enquanto um Data Template é usado para o WPF saber como representar algum dado. Porém, na representação de dados, apenas o template não é suficiente. É necessário que haja elementos de apresentação, os Content Presenters, que criam uma representação visual do que foi definido pelo template de dados. Além disso, é preciso que haja uma ligação entre o dado propriamente dito e a forma de representar visualmente esses dados. Essa ligação é chamada de Data Binding. É importante ressaltar que data binding em WPF é mais poderoso que em outros frameworks porque pode ser uni ou bidirecional, permitindo que a interface atualize automaticamente os dados em resposta a ações do usuário. Ainda, é possível realizar a conversão dos dados, tanto quando os dados serão apresentados para o usuário quanto quando os dados serão manipulados pela aplicação; não apenas alterar o tipo do mesmo, mas alterar até mesmo a sua representação, utilizando os converters. O último passo nessa visualização de dados é o layout. Ele é responsável por ajustar o tamanho e a posição de todos os controles criados.

...
Quer ler esse conteúdo completo? Tenha acesso completo