20 abril, 2010

Silverlight 4 - Novo xaml parser e suporte namespaces xml

O Silverlight 4 foi lançado na semana passada é já existe uma tonelada de posts com informações a respeito das novidades. Eu estava lendo um post do blog do Silverlight SDK e encontrei uma novidade interessante sobre a qual não se está falando muito. O parser de xaml do Silverlight 4 agora respeita corretamente as definições de namespace xml. Isso tem várias implicações:

  • Agora o namespace padrão dos seus arquivos xml não precisa mais ser “http://schemas.microsoft.com/winfx/2006/xaml/presentation”. Você pode mudar se for útil/necessário para sua aplicação (por exemplo, se você estiver gerando xaml dinamicamente utilizando apenas controles customizados).
  • Com esse suporte, agora é possível criar os seus próprios namespaces, agrupando vários namespaces da sua apliação ou mesmo de diversos assemblies distintos.
  • Frameworks como o Silverlight Toolkit e o SDK já estão tirando proveito disso, definindo seus próprios namespaces para simplificar sua utilização e eliminar a necessidade de ter que conhecer toda a estrutura desses projetos para saber onde estão os controles que queremos usar.

Ou seja, agora é possível ter acesso a todos os controles do Silverlight Toolkit ou SDK acrescentando apenas 2 namespaces na sua tela, como abaixo (mas lembre-se que ainda é necessário fazer referencias as dlls):

xmlns:toolkit=”http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit xmlns:sdk=”http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk

Tudo isso é muito interessante e muito legal mas o que me deixou intrigado é que eu não estava conseguindo encontrar informações em nenhum lugar que explicassem como é que eu poderia fazer meus frameworks e apis tirarem proveito desses recursos. Cheguei até a achar por um momento que esses novos namespaces estivesses fixos no Silverlight 4, mas como não era esse o discurso, tinha que have um jeito de implementarmos isso em nossas aplicações.

Foi então que eu tive a idéia de seguir um conselho que o Scott Hanselman vive repetindo quase como um mantra que é “ler código alheio para se tornar um programador melhor”. Tendo isso em mente eu fui ao codeplex e comecei a fuçar no código fonte do Silverlight Toolkit, até que achei o que estava procurando. Para que você possa tirar proveito desse recurso em suas próprias aplicações e frameworks, basta marcar o assembly com os atributos XmlnsPrefix e XmlnsDefinition, como demonstrado abaixo:

[assembly: XmlnsPrefix(http://schemas.wf.com.br/sdk, "wf")] [assembly: XmlnsDefinition(http://schemas.wf.com.br/sdk, "WF.Silverlight")] [assembly: XmlnsDefinition(http://schemas.wf.com.br/sdk, "WF.Silverlight.Controles")]

O lugar ideal para definir esses atributos é no arquivo AssemblyInfo do projeto. Para poder utilizar esses atributos é necessário referenciar o namespace System.Windows.Markup nas instruções de using no top da página.

O atributo XmlnsPrefix serve para criar um namespace e pré-definir qual será o seu prefixo quando um controle for adicionado diretamente pelo Visual Studio ou Expression Blend. Geralmente haverá apenas 1 atributo desse por projeto.

O atributo XmlnsDefinition é o responsável por vincular um namespace xml com um namespace do assembly. Esse atributo pode ser adicionado ao assembly quantas vezes for necessário. Geralmente haverá um atributo desse para cada namespace do assembly que contenha controles ou elementos que se deseja disponibilizar no xaml.

Uma coisa muito interessante que eu descobri é que os namespaces que você criar aparecem no intellisense do Visual Studio 2010, como pode ser visto abaixo:

 image

Espero que essas dicas tenham sido úteis. Eu sei que vou tirar proveito dessa nova funcionalidade nos meus próximos projetos.

Update 30/04/2010 : Encontrei um problema na implementação que demonstrei aqui. Devido a uma limitação do compilador do Silverlight, não é possível atribuir a propriedade x:Name a um controle definido por meio do novo xmlns se esse controle fizer parte do mesmo assembly em que está sendo utilizado. Ficou meio confuso, então vou tentar dar um exemplo:

Temos uma solution com um projeto. Esse projeto tem o seguinte xmlns:  xmlns:my=http://schema.minhaempres.silverlight e um controle chamado ControleA que está sendo “coberto” por esse xmlns. Se eu criar um ControleB nesse projeto, definir o uso do namespace “my” e utilizar o ControleA com a seguinte sintax, vai funcionar : <my:ControleA />. Se eu tentar atribuir a propriedade x:Name no meu ControleA, não vai mais funcionar. O problema é apenas com a propriedade x:Name e apenas se ambos os controles estiverem no mesmo assembly. Muitas vezes a gente consegue criar telas inteiras sem precisar dar nomes aos campos, principalmente graças ao uso de data binding, mas se for necessário fazer alguma animação, manipular o controle via code behind ou utilizar em algum TemplatePart de outro controle, tem que ter name.

Agora a boa notícia. Como esse erro só acontece se os 2 controles em questão estiverem no mesmo assembly, o workaround é simples, basta utilizar a declaração convencional de xmlns que usamos normalmente, onde dizemos o nome do assembly e namespace da classe.

4 comentários:

César Rabelo - AnalisUsabilidade disse...

Esse caminho http://... do xnlns tem que ser um caminho válido na web?

Kelps Leite de Sousa disse...

Não. Essa url não precisa existir pois é apenas uma espécie de ID para o namespace.

Mas se você quiser, pode usar uma url real e colocar algum tipo de help nela, por exemplo.

Gabriel disse...

Oi Kelps,
Deixe eu te perguntar não entendo muito sobre xml, mas o que muda ?
tipo que diferença faz eu criar um namespace para meus controles (tipo criar um namespace pras minhas views?) tem alguma diferença prática?

Não pergunto pejorativamente, apenas não tenho idéia de pra que serve o namespace em xml.

É para uma espécie de reflector xml?
ou é para metadata?

Valew

Kelps Leite de Sousa disse...

Gabriel,
Se você criar um namespace xml para apenas uma pasta do seu projeto (um namespace do seu assembly), realmente não terá muito beneficio.

O ganho que se tem com essa técnica é quando temos uma biblioteca ou projeto grande. Nesses casos podemos "agrupar" vários namespaces do assembly sob um único namespace de xml. Isso faz com que não seja mais necessário ter várias declarações xmlns nos seus códigos xaml que serviriam apenas para referenciar controles da sua aplicação. Outra coisa interessante é que esse namespace xml pode englobar namespaces de vários assemblies, fazendo com que a criação e utilização de bibliotecas corporativas se torne bem mais simples.

Espero ter resolvido sua dúvida.