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 Rodrigues



O 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.

Linhas e colunas definidas

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>
Linhas e colunas ajustadas e sem conteúdo

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).

Linhas e colunas com dimensões fixas e relativas

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).

Controles organizados no grid

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.

Utilizando Rowspan e Colspan

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.

Resultado do exemplo prático

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.

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).