Desenvolvimento - ASP. NET
WPF Grid: explorando o componente
Conheça em detalhes o componente WPF e analise suas principais propriedades e aprendam como montar um layout organizado a partir de suas linhas e colunas no .NET.
por Joel RodriguesO WPF (Windows Presentation Foundation) é parte integrante do .NET Framework e foi criado para, entre outros fins, permitir e facilitar a criação de aplicações de interface rica, ou seja, interface mais elaborada (efeitos, formas, layout, etc), quando comparada com as interfaces comuns dos Windows Forms.
Entre os vários componentes disponíveis para a organização do layout está o Grid, elemento principal dessa categoria e que é utilzado na maioria das telas de aplicações WPF, devido a sua flexibilidade e funcionalidades oferecidas. Neste artigo vamos conhecer em detalhes esse componente, analisando suas principais propriedades e aprendendo como montar um layout organizado a partir de suas linhas e colunas.
Esse componente, como a maioria dos demais, está disponível na ToolBox e pode ser arrastado para o editor visual da janela, ou para o código XAML. Caso prefira editar o código diretamente, você pode inserir esse componente na janela utilizando as tags <Grid></Grid>> Quando se cria uma aplicação WPF no Visual Studio, a janela MainWindow já vem com um grid como componente principal, dentro do qual podem ser inseridos os demais elementos da interface.
Linhas e colunas
A princinpal característica desse componente, e que o torna tão interessante para a construção de layouts bem organizados, é a sua divisão em linhas e colunas.
Por padrão, quando se insere um novo grid na interface ele é criado como um container simples, sem divisões. Para dividí-lo em linhas e colunas, devemos adicionar entre as tags e em as tags RowDefinitions (para linhas) e ColumnDefinitions (para colunas), como mostra a Listagem 1.
Listagem 1: Atributos RowDefinitions e ColumnDefinitions
<Grid> <Grid.RowDefinitions> </Grid.RowDefinitions> <Grid.ColumnDefinitions> </Grid.ColumnDefinitions> </Grid>
Esses atributos, por sua vez, devem conter subatributos que definem as características de cada linha e coluna do grid. Entre as tags RowDefinitions devemos inserir um conjunto de tags RowDefinition com o atributo Height bem definido, que representa a altura de cada linha criada. Já entre as tags ColumnDefinitions devem ser inseridas tags ColumnDefinition, dessa vez com o atributo Width definido, o que representa a largura de cada coluna. Na Listagem 2 vemos um exemplo de definição de linhas e colunas.
Listagem 2: Definição das linhas e colunas
<Grid> <Grid.RowDefinitions> <RowDefinition Height="100"/> <RowDefinition Height="100"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="100" /> <ColumnDefinition Width="100" /> </Grid.ColumnDefinitions> </Grid>
No exemplo acima foram criadas duas linhas e duas colunas, cada uma com 100px de largura ou altura. Na Figura 1 podemos ver como ficou o layout da janela.
Figura 1: Linhas e colunas definidas
Aqui vale destacar um detalhe interessante do editor visual do IDE: nas extremidades da janela são exiidas as dimensões das linhas e colunas do grid. Note, porém, que a segunda linha e a segunda coluna não parecem estar com 100px de altura ou largura, diferente das primeiras. Isso ocorre porque o grid, no total, possui mais de 200px de altura e largura. Portanto, a soma das dimensões de suas linhas e colunas deve ser igual à sua altura e largura totais.
Quando ocorre esse tipo de situação, o editor considera que a última linha e coluna, ou aquelas que não tiveram suas dimensões bem definidas, devem assumir como altura e largura o espaço restante no grid. No exemplo acima, mesmo com a segunda linha e coluna tendo suas dimensões fixadas, elas foram automaticamente adaptadas para ocupar todo o espaço restante.
Altura e largura
A altura e largura das linhas e colunas, respectivamente, podem ser definidas com três tipos de valores diferentes:um valor numérico, Auto ou * (asterísco).
Os valores numéricos, quando atribuídos às larguras e alturas, fixam essas dimensões em pixeis, de acordo com o número informado. No exemplo da Listagem 1 foram utilizados 100px para todas as dimensões.
Quando atribuimos o valor Auto, a largura ou altura se adapta automaticamente ao seu conteúdo, expandindo ou contraindo para acomodar os componentes em seu interior. A Listagem 2 mostra o grid do exemplo anterior com as larguras e alturas definidas como Auto. Note, na
Figura 2, que as linhas e colunas praticamente desapareceram, pois como não contém conteúdo, suas dimensões são automaticamente ajustadas para zero.
Listagem 2: Definição das dimensões com Auto
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> </Grid>
Figura 2: Linhas e colunas ajustadas e sem conteúdo
O *, por sua vez, faz com que as linhas e colunas se ajustem à largura total do grid, ocupando todo o espaço disponível. O * também pode aparecer precedido por um valor numérico, que faz com que o espaço disponível seja dividido em partes relativas ao valor indicado. No exemplo da Listagem 3 temos uma linha e uma coluna com largura e altura fixadas em 100px, e outras com as dimensões relativas, ocupando o espaço restante.
Listagem 3: Dimensões relativas com *
<Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> <RowDefinition Height="2*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="2*" /> </Grid.ColumnDefinitions> </Grid>
Para entender melhor o funcionamento, vamos observar o editor visual (Figura 3).
Figura 3: Linhas e colunas com dimensões fixas e relativas
Note os valores na borda do grid indicando que, enquanto a primeira linha possui 50px de altura, a segunda linha possui 1* e a terceira 2*. Ou seja, após descontar os 50px da primeira linha, o espaço restante foi divido em duas partes, onde a segunda equivale ao dobro da primeira. O mesmo vale para as colunas.
Posicionando controles no grid
Ao inserir um controle em um grid ele passa a suportar as propriedades Grid.Row e Grid.Column, que indicam em qual linha e coluna ele deve ser posicionado. É interessante sempre definir essas propriedades para evitar confusões sobre o posicionamento de cada componente.
Observação: a numeração das linhas e colunas começa em zero.
Vamos então inserir alguns controles no grid e posicioná-los, conforme mostra a Listagem 4.
Listagem 4: Posicionando controles no grid
<Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="*"/> <RowDefinition Height="2*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="2*" /> </Grid.ColumnDefinitions> <Button Content="Botão (0,1)" Grid.Row="0" Grid.Column="1"/> <TextBlock Text="TextBlock (1,2)" Grid.Row="1" Grid.Column="2"/> <TextBox Text="TextBlock (2,1)" Grid.Row="2" Grid.Column="1"/> </Grid>
Olhando a parte visual do editor podemos entender como os controles foram organizados (Figura 4).
Figura 4: Controles organizados no grid
Rowspan e Colspan
Quem conhece HTML deve estar familiarizado com essas propriedades Quando definidas em um controle que esteja em um grid, elas permitem que esse controle ocupe mais de uma linha e/ou coluna. Nesse caso, controle deve ser posicionado em uma célua, como visto no exemplo anterior, e então ele ocupará as células seguintes, dependendo do valor que for atribuído às propriedades Rowspan e Colspan. Vamos alterar o exemplo anterior, fazendo com que o botão passe a ocupar a linha e coluna seguintes (iremos remover o TextBlock), conforme a Listagem 5.
Listagem 5: Controle ocupando mais de uma linha e coluna
<Button Grid.Row="0" Grid.Column="1" Content="Botão (0,1)" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
Agora o botão ocupará a coluna à sua direita e a linha abaixo, como vemos na Figura 5.
Figura 5: Utilizando Rowspan e Colspan
Exemplo prático
Para finalizar este artigo e facilitar a assimilação do que foi explicado, vamos fazer um pequeno exemplo prático, criando uma janela de cadastro com alguns campos e botões. O código é exibido na Listagem 6 e o resultado pode ser visto na Figura 6.
Listagem 6: Código do exemplo prático
<Grid> <Grid.RowDefinitions> <RowDefinition Height="50"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="30"/> <RowDefinition Height="*"/> <RowDefinition Height="30"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Text="Cadastro de Clientes" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" FontSize="30"/> <TextBlock Text="Nome" Grid.Row="1" Grid.Column="0" /> <TextBox Text="João da silva" Grid.Row="1" Grid.Column="1" /> <TextBlock Text="Telefone" Grid.Row="2" Grid.Column="0" /> <TextBox Text="9977-8855" Grid.Row="2" Grid.Column="1" /> <TextBlock Text="Email" Grid.Row="3" Grid.Column="0" /> <TextBox Text="joao@silva.com" Grid.Row="3" Grid.Column="1" /> <TextBlock Text="Observações" Grid.Row="4" Grid.Column="0" /> <TextBox Text="Digite as observações desse cliente" Grid.Row="4" Grid.Column="1" /> <StackPanel Orientation="Horizontal" Grid.Row="5" Grid.ColumnSpan="2"> <Button Content="Salvar" Width="100"/> <Button Content="Excluir" Width="100"/> <Button Content="Cancelar" Width="100"/> </StackPanel> </Grid>
Quando executamos o projeto, temos uma janela com seus controles bem organizados e que se adaptam ao tamanho da tela.
Figura 6: Resultado do exemplo prático
Agora cabe ao leitor criar vários layouts e explorar as possibilidades de organização de controles utilizando o grid.