domingo, 16 de novembro de 2008

Conceitos do XAML (zãmeu) – Parte II

Neste artigo vou explicar mais detalhadamente alguns conceitos básicos do XAML. Este artigo é composto pelos seguintes itens:

  • Propriedades e Layout (parte I);
  • Containeres (este artigo);
  • Brushes;
  • Desenhos geométricos;

Containeres (Containers)

Em quase todos os artigos aparece o tal do container, mas afinal o quem são eles?

Bom. Os Containers são controles pais que podem conter filhos, ou seja, podem conter controles dentro deles, podendo ser ate mesmo outro container ou o mesmo. Por exemplo, dentro de um Canvas eu posso ter outro Canvas e dentro desse eu posso ter um StackPanel, independente da ordem ou tipo. Container agrupa controles e define a raiz do XAML em questão. Sendo assim todo controle XAML, como por exemplo, o Page.xaml, possui um controle raiz que deve ser um container, são eles: Canvas, StackPanel e Grid.

Canvas

O mais famoso dos containers. O controle Canvas possui a característica de posicionar os elementos em uma espécie de plano cartesiano, onde para seus controles filhos pode ser informada a posição em que serão desenhados, o X e o Y. Isso é definido pela attached property Canvas.Left e Canvas.Top respectivamente.

O xaml abaixo mostra como definir esta propriedade.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas x:Name="LayoutRoot" Background="White">
<Rectangle Fill="Green" Width="200" Height="100"
Canvas.Left="50"/>
<Rectangle Fill="Black" Width="200" Height="100"
Canvas.Left="100" Canvas.Top="180"/>
</Canvas>
</UserControl>

A figura abaixo mostra o design deste XAML.

image

StackPanel

O StackPanel possui a característica de orientar seus controles filhos através da propriedade Orientation, que pode ter os valores Horizontal e Vertical. O XAML abaixo mostra um StackPanel com alguns controles sendo orientado horizontalmente e verticalmente, sendo, um StackPanel dentro do outro.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<StackPanel x:Name="LayoutRoot" Background="White">
<Rectangle Fill="Green" Width="100" Height="50"
Canvas.Left="50" Margin="0,10,0,0"/>
<Rectangle Fill="Black" Width="100" Height="50"
Canvas.Left="100" Canvas.Top="180"/>
<StackPanel Width="100" Height="160" Background="PeachPuff"
Orientation="Horizontal">
<Button Content="Clique" Width="50" Height="25" />
<Ellipse Fill="Blue" Width="50" Height="50"></Ellipse>
</StackPanel>
</StackPanel>
</UserControl>

(OBS: Por padrão o StackPanel recebe o valor Vertical na propriedade Orientation caso nenhum valor seja informado).

Abaixo uma figura ilustrando o design deste exemplo.

image

Se desejar deixar um espaço entre os controles basta mudar a propriedade Margin (Margem) dos controles filhos do StackPanel. A Propriedade Margin recebe um objeto Thickness que por sua vez recebe 4 valores sendo a quantidade de pixels que o controle se afastará dos vizinhos, na ordem esses 4 valores são respectivamente para a Esquerda (LEFT), Topo (TOP), Direita (RIGHT) e finalmente para Baixo (BOTTOM).

Já o valor Vertical da propriedade Orientation do StackPanel desenha seus controles verticalmente, um embaixo do outro.

(OBS.: A maioria dos controles que fazem parte do layout do Silverlight aceita a propriedade Margin).

Grid

O Grid foi adotado como controle container padrão no silverlight 2 (nas versões anteriores o container padrão era o Canvas) quando se cria um projeto, por exemplo. Este container traz muita facilidade na hora de estilizar o layout das páginas, pois utiliza o conceito de uma tabela (igual as tables no HTML) para desenhar os elementos filhos. Você pode tanto adicionar colunas como adicionar linhas e definir qual será sua largura (Width) e sua altura (Height) respectivamente.

O XAML e a figura abaixo mostra o Grid em ação.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<Button Content="Clique Aqui!" Width="100"
Height="35" Canvas.ZIndex="1"/>
<Ellipse Fill="Red" Width="110" Height="40" />
</Grid>
</UserControl>

image


(OBS: Utilizamos o Canvas.ZIndex para posicionar o botão na frente do círculo, isso funcionaria se o XAML do círculo fosse escrito primeiro que o do botão).

Caso não queira linhas ou colunas na Grid você pode optar por não adicioná-las, o Grid entende que possui somente uma linha e uma coluna, ambas com 100% largura (Width) e altura(Height).

Vamos criar um simples formulário de cadastro utilizando o container Grid para você ver como é simples e como muito parecido com o table do HTML. Primeiramente você define o Grid e algumas de suas propriedades como Background (Cor de fundo) e ShowGridLines (mostra a borda das colunas e linhas, muito utilizado para identificá-las).

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White"
ShowGridLines="True">
<!-- Content do Grid -->
</Grid>
</UserControl>

Após, é preciso definir as colunas, que nesse caso serão duas, uma para o rótulo do campo e a outra para o controle de entrada do campo, como por exemplo, o TextBox. O Grid possui uma coleção de colunas e linhas. Para adicionar uma coluna basta inserir um ColumnDefinition dentro da coleção de colunas, o Grid.ColumnDefinitions.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White"
ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
</UserControl>

(OBS: para que as propriedades Width e Height representam um altura/largura de100% utiliza-se o valor "*")

A figura abaixo mostra o design deste layout.

image

Basta seguir o mesmo caminho para inserir linhas no Grid. Assim como para as colunas, o Grid possui uma coleção de linhas, o Grid.RowDefinitions. Dentro desta coleção basta adicionar um ou mais RowDefinition. O XAML abaixo mostra como fica o layout de nosso formulário.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White"
ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
</UserControl>

A figura abaixo mostra a aplicação silverlight em execução.

image

Observe como a propriedade ShowGridLines do container Grid ajuda a visualizar o layout da aplicação.

Agora so nos resta adicionar os controles em nosso formulário.

Para ordenar os controles filhos do container Grid utiliza-se as propriedades Grid.Column (começa do valor 0 que é padrão) para especificar a coluna em que o determinado controle será posicionado e a propriedade Grid.Row (o mesmo de Grid.Column) que especifica a linha onde será apresentado no Grid.

O XAML abaixo mostra a aplicação completa.

<UserControl x:Class="Blog_XamlBasics2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White"
ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<!--COLUNA 0 - ROTULOS-->
<!--
Observe que não é preciso informar Gri.Column para a
primeira coluna pois o valor 0 já é padrão para todos
controles filhos de um controle container Grid. O mesmo
se aplica para Grid.Row.
-->
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Center"
Text="Nome:"/>
<!--Agora é preciso informar a linha (Grid.Row) dos controles-->
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Center"
Grid.Row="1" Text="Idade:"/>
<TextBlock HorizontalAlignment="Right"
VerticalAlignment="Center"
Grid.Row="2" Text="Email:"/>

<!--COLUNA 1 - CAMPOS-->
<!--
Agora é preciso informar a coluna (Grid.Column) para o
primeiro campo e para o restante informar tanto a coluna
quanto a linha(Grid.Row).
-->
<TextBox x:Name="txtNome" Width="200" Height="25"
Margin="5" HorizontalAlignment="Left"
Grid.Column="1"/>
<TextBox x:Name="txtIdade" Width="50" Height="25"
Margin="5" HorizontalAlignment="Left"
Grid.Column="1" Grid.Row="1"/>
<TextBox x:Name="txtEmail" Width="200" Height="25"
Margin="5" HorizontalAlignment="Left"
Grid.Column="1" Grid.Row="2"/>

<!--BOTÃO CADASTRAR-->
<Button x:Name="btnCadastrar" Width="100" Height="25"
HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Column="1" Grid.Row="3" Content="Cadastrar"
Click="btnCadastrar_Click"/>
</Grid>
</UserControl>

(OBS: Não esqueça de tirar a propriedade ShowGridLines do controle Grid)

Observe que adicionamos um Evento (EventHandler) no Click do botão Cadastrar para mostrar uma mensagem de sucesso simulando que o cadastro foi efetuado e apresentando os dados informados. Abaixo segue o código do evento de Click do botão.

private void btnCadastrar_Click(object sender, RoutedEventArgs e)
{
string cadastro = "O Cliente {0} do e-mail {1} e idade {2} " +
"foi cadastrado com sucesso!";

MessageBox.Show(string.Format(cadastro, txtNome.Text,
txtEmail.Text, txtIdade.Text));
}

As figuras abaixo mostram o programa em execução.

image

image

Clicando no botão Cadastrar...

image

Obrigado e até a próxima.

2 comentários:

Thiago Boccio disse...

Show de bola! Parábens...

Anônimo disse...

Bom!