WPF - Usando o controle Grid


Já publiquei diversos artigos sobre o Windows Presentation Foundation - WPF, e, neste artigo eu volto ao assunto para falar sobre um controle muito usado. O controle Grid.

Nos exemplos deste artigo eu estou usando o Visual Basic 2010 Express Edition onde no menu File -> New Project selecionei o template WPF Application e informei o nome UsandoGrid. Na figura abaixo vemos a solução criada :

O container Grid é o mais familiar e poderoso controle WPF. A cada nova janela Windows aberta no WPF temos um controle Grid incluído.

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>

</Grid>

</Window>

Quando adicionado a uma janela (Window) , ele consiste em um Grid de uma única célula. Linhas verticais e horizontais adicionais podem ser adicionadas via código ou o no descritor WPF. Você pode definir a propriedade ShowGridLines para exibir uma grade linhas e assim facilitar o posicionamento dos elementos no Grid.

O Grid permite que você posicione os controles dentro de células definidas pelo usuário.Os controles colocados nas células mantêm uma margem fixa entre duas ou mais bordas do controle ou da célula quando a janela for redimensionada.

Dessa forma o controle Grid pode ser visto como um painel de layout que organiza seus controles filhos em uma estrutura tabular de linhas e colunas. Sua funcionalidade é semelhante à tabela HTML, mas mais flexível. Uma célula pode conter vários controles, que podem ocupar várias células e até mesmo se sobreporem umas as outras.

Um painel Grid pode ser usada para criar interfaces de usuário complexas, onde precisamos colocar vários elementos em uma tabela de layout de linhas e colunas.

O comportamento de redimensionamento dos controles é definida pelas propriedades HorizontalAlignment e VerticalAlignment que definem as âncoras. A distância entre a âncora e a linha do grid é definida pela margem do controle.

O elemento Grid em XAML representa um painel Grid. O trecho de código a seguir cria um elemento Grid e define seu plano de fundo, largura, altura, vertical e propriedades de alinhamento horizontal:

<Grid Name="GridMacoratti" Background="LightGoldenrodYellow" Width="280" Height="220"
VerticalAlignment="Top" HorizontalAlignment="Center" >
</Grid>

Definindo linhas e colunas

O controle Grid possui três propriedades principais:

- RowDefinitions - que representa uma coleção de itens RowDefinition;
- ColumnDefinitions - que presenta uma coleção de itens ColumnDefinition;
- ShowGridLines - que define se as linhas da grade de um painel são visíveis ou não;

O Grid tem por padrão uma linha e uma coluna e para criar linhas e colunas adicionais você tem que incluir itens RowDefinition a coleção RowDefinitions e itens ColumnDefinition a coleção ColumnDefinitions.

No exemplo a seguir vamos definir um Grid com 3 linhas e e colunas :

Podemos colocar qualquer controle WPF no interior de um Grid usando suas propriedades Grid.Row e Grid.Column que representam em qual coluna e em qual linha o controle será colocado, sendo que os valores das linhas e colunas começam em zero. (Isso significa que se existem 3 colunas em um Grid a primeira seria a coluna 0, a segunda a coluna 1 e a terceira a coluna 2)

Obs: Por padrão, linhas e colunas ocupam a menor quantidade de espaço necessário para acomodar o maior conteúdo em qualquer célula contida em uma determinada linha ou coluna.

No próximo exemplo vamos incluir no Grid que definimos acima um controle TextBox em uma célula do grid que esta na segunda linha e segunda coluna:


<TextBox Grid.Row="1" Grid.Column="1" Foreground="Blue" Text="Nome" Height="30"   VerticalAlignment="Top" />

Grid.Row = 1 - indica a segunda linha;
Grid.Column = 1 - indica a segunda coluna;


Nota: É possível posicionar com precisão elementos filho em um Grid usando uma combinação da propriedade Margin e da propriedade de alianhamento.

A seguir temos o mesmo exemplo onde preenchemos cada célula do Grid via código XAML usando o controle TextBlock:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid Name="MacorattiGrid" Width="400" Background="LemonChiffon" ShowGridLines="True">
       <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="45" />
            <RowDefinition Height="45" />
            <RowDefinition Height="45" />
        </Grid.RowDefinitions>
      <TextBlock FontSize="14" FontWeight="Bold" Grid.Row="0" Grid.Column="0" Foreground="Blue" 
                   Text="Nome" Height="20" VerticalAlignment="Top"  />
        <TextBlock FontSize="14" FontWeight="Bold" Grid.Row="0" Grid.Column="1" Foreground="Blue" 
                   Text="Email" Height="20" VerticalAlignment="Top" />
        <TextBlock FontSize="14" FontWeight="Bold" Grid.Row="0" Grid.Column="2" Foreground="Blue" 
                   Text="Cidade" Height="20" VerticalAlignment="Top"/>
        <TextBlock FontSize="12" Grid.Row="1" Grid.Column="0">José Carlos Macoratti</TextBlock>
        <TextBlock FontSize="12" Grid.Row="1" Grid.Column="1">macoratti@yahoo.com</TextBlock>
        <TextBlock FontSize="12" Grid.Row="1" Grid.Column="2">Brasilia</TextBlock>
        <TextBlock FontSize="12" Grid.Row="2" Grid.Column="0">Janice Raquel</TextBlock>
        <TextBlock FontSize="12" Grid.Row="2" Grid.Column="1">janice@bol.com.br</TextBlock>
        <TextBlock FontSize="12" Grid.Row="2" Grid.Column="2">São Paulo</TextBlock>
    </Grid>
</Window>

Neste outro exemplo temos outra possibilidade de utilização do controle Grid:


<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid Name="MacorattiGrid" Width="400" Background="LemonChiffon" ShowGridLines="True">
        <Grid VerticalAlignment="Top" HorizontalAlignment="Left" ShowGridLines="True" Width="250" Height="100">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <TextBlock FontSize="20" Foreground="Green" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="0">Vendas - 2011</TextBlock>
            <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="0">Janeiro</TextBlock>
            <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="1">Fevereiro</TextBlock>
            <TextBlock FontSize="12" FontWeight="Bold" Grid.Row="1" Grid.Column="2">Março</TextBlock>
            <TextBlock Grid.Row="2" Grid.Column="0">50000</TextBlock>
            <TextBlock Grid.Row="2" Grid.Column="1">100000</TextBlock>
            <TextBlock Grid.Row="2" Grid.Column="2">150000</TextBlock>
            <TextBlock FontSize="18" Foreground="Blue" FontWeight="Bold" Grid.ColumnSpan="3" Grid.Row="3">Vendas Total: 300000</TextBlock>
        </Grid>
    </Grid>
</Window>

Podemos criar um Grid em tempo de execução via código usando a classe Grid. Abaixo reproduzimos o mesmo Grid definindo acima onde o resultado da execução do código do arquivo MainWindow.xaml.vb pode ser visto abaixo:

Class MainWindow

    Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        'Cria um Grid como o raiz do elemento Panel
        Dim MacorattiGrid As New Grid()
        MacorattiGrid.Height = 100
        MacorattiGrid.Width = 250
        MacorattiGrid.ShowGridLines = True
        MacorattiGrid.HorizontalAlignment = Windows.HorizontalAlignment.Left
        MacorattiGrid.VerticalAlignment = Windows.VerticalAlignment.Top

        ' Define e Inclui Linhas e Colunas
        Dim colDef1 As New ColumnDefinition
        Dim colDef2 As New ColumnDefinition
        Dim colDef3 As New ColumnDefinition
        MacorattiGrid.ColumnDefinitions.Add(colDef1)
        MacorattiGrid.ColumnDefinitions.Add(colDef2)
        MacorattiGrid.ColumnDefinitions.Add(colDef3)

        Dim rowDef1 As New RowDefinition
        Dim rowDef2 As New RowDefinition
        Dim rowDef3 As New RowDefinition
        Dim rowDef4 As New RowDefinition
        MacorattiGrid.RowDefinitions.Add(rowDef1)
        MacorattiGrid.RowDefinitions.Add(rowDef2)
        MacorattiGrid.RowDefinitions.Add(rowDef3)
        MacorattiGrid.RowDefinitions.Add(rowDef4)

        Dim txt1 As New TextBlock
        txt1.Text = "Vendas - 2011"
        txt1.FontSize = 20
        txt1.FontWeight = FontWeights.Bold
        Grid.SetColumnSpan(txt1, 3)
        Grid.SetRow(txt1, 0)
        MacorattiGrid.Children.Add(txt1)

        Dim txt2 As New TextBlock
        txt2.Text = "Janeiro"
        txt2.FontSize = 12
        txt2.FontWeight = FontWeights.Bold
        Grid.SetRow(txt2, 1)
        Grid.SetColumn(txt2, 0)
        MacorattiGrid.Children.Add(txt2)

        Dim txt3 As New TextBlock
        txt3.Text = "Fevereiro"
        txt3.FontSize = 12
        txt3.FontWeight = FontWeights.Bold
        Grid.SetRow(txt3, 1)
        Grid.SetColumn(txt3, 1)
        MacorattiGrid.Children.Add(txt3)

        Dim txt4 As New TextBlock
        txt4.Text = "Março"
        txt4.FontSize = 12
        txt4.FontWeight = FontWeights.Bold
        Grid.SetRow(txt4, 1)
        Grid.SetColumn(txt4, 2)
        MacorattiGrid.Children.Add(txt4)

        Dim txt5 As New TextBlock
        txt5.Text = "50.000"
        Grid.SetRow(txt5, 2)
        Grid.SetColumn(txt5, 0)
        MacorattiGrid.Children.Add(txt5)

        Dim txt6 As New Controls.TextBlock
        txt6.Text = "100.000"
        Grid.SetRow(txt6, 2)
        Grid.SetColumn(txt6, 1)
        MacorattiGrid.Children.Add(txt6)

        Dim txt7 As New TextBlock
        txt7.Text = "150.000"
        Grid.SetRow(txt7, 2)
        Grid.SetColumn(txt7, 2)
        MacorattiGrid.Children.Add(txt7)

        ' Incluir o TextBlock final a célula do Grid
        Dim txt8 As New TextBlock
        txt8.FontSize = 14
        txt8.FontWeight = FontWeights.Bold
        txt8.Text = "Total Vendas: 300000"
        Grid.SetRow(txt8, 3)
        Grid.SetColumnSpan(txt8, 3)
        MacorattiGrid.Children.Add(txt8)

        Me.Content = MacorattiGrid

    End Sub
End Class

O tamanho da célula pode ser definido como um valor absoluto de unidades lógicas, como um valor percentual ou de forma automática:

No exemplo a seguir temos um Grid em um leiaute onde definimos 4 linhas e 2 colunas assim defnidas:


<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Usando o controle Grid" Height="350" Width="525">
    <Grid Name="MacorattiGrid" Width="400" Background="LightSalmon" ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="28" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="300" />
        </Grid.ColumnDefinitions>
        <Label Grid.Row="0" Grid.Column="0" Content="Nome:"/>
        <Label Grid.Row="1" Grid.Column="0" Content="E-Mail:"/>
        <Label Grid.Row="2" Grid.Column="0" Content="Assunto:"/>
        <TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
        <TextBox Grid.Column="1" Grid.Row="1" Margin="3" />
        <TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
        <Button Grid.Column="1" Grid.Row="3" HorizontalAlignment="Right" 
            MinWidth="80" Margin="3" Content="Enviar"  />
    </Grid>
</Window>

Usando o controle GridSpliter para redimensionar o Grid

A WPF fornece um controle chamado GridSplitter. Este controle é adicionado como qualquer outro controle para uma célula da grade. Ele permite que o usuário redimensione as linhas e colunas do controle grid na direção horizontal e vertical.

No exemplo abaixo temos um exemplo de utilização do controle GridSplitter

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Usando o controle Grid" Height="350" Width="525">
    <Grid Name="MacorattiGrid" Width="466" Background="LemonChiffon" ShowGridLines="True" 
          Canvas.Top="119" Canvas.Left="8" Height="200">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50*" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="50*" />
        </Grid.RowDefinitions>
       <GridSplitter 
               ResizeDirection="Rows"
                Grid.Column="0"
                Grid.ColumnSpan="10"
               Grid.Row="1" 
                Width="Auto"
                Height="3"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                Margin="0"
                Background="Green"/>
    </Grid>
</Window>

Abaixo vemos o projeto acima em execução:

A melhor maneira de alinhar um GridSplitter é colocá-lo em sua própria coluna definida como auto. Fazendo dessa forma, você evita a sobreposição de células adjacentes.

Para garantir que o GridSplitter altere o tamanho da célula anterior e da seguinte você tem que definir a propriedade ResizeBehavior para PreviousAndNext.

Exemplo:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Label Content="Left" Grid.Column="0" />
    <GridSplitter HorizontalAlignment="Right" 
                  VerticalAlignment="Stretch" 
                  Grid.Column="1" ResizeBehavior="PreviousAndNext"
                  Width="5" Background="#FFBCBCBC"/>
    <Label Content="Right" Grid.Column="2" />
</Grid>

O divisor do GridSplitter reconhece a direção para a qual deve redirecionar de acordo com a relação entre a sua altura e a largura mas você pode também configurar manualmente a propriedade ResizeDirection para linhas ou colunas:
Exemplo:

<GridSplitter ResizeDirection="Columns"/>

Formatando o Grid

A propriedade background do Grid define as cores de fundo de uma grade.

No exemplo a seguir estamos definindo um gradiente linear para desenhar o fundo do Grid.

Podemos usar a propriedade background para definir uma imagem como fundo de uma grade.V

No exemplo a seguir definimos como fundo a imagem Garden.jpg e também a opacidade da imagem:

E assim apresentei os principais recursos do controle Grid e sua utilização. Existem mais recursos que podem ser usados para incrementar o controle ajustando-o à sua necessidade.

Simples , simples assim...

Pegue o projeto completo aqui: UsandoGrid.zip

Eu sei é apenas WPF, mas eu gosto...

Referências:

José Carlos Macoratti