ListBox com Header no WPF

Há algum tempo precisei usar ListBox em uma aplicação WPF, porém precisava que o mesmo tivesse um Header, então decidi criar um estilo alterando a Template do ListBox para que o mesmo passasse a ter um Header.
Para começar criei uma classe chamada MeuListBox herdando da classe ListBox, depois registrei uma DependencyProperty chamada Header:


public class MeuListBox : ListBox
{
    public FrameworkElement Header
    {
        get { return (FrameworkElement)GetValue(HeaderProperty); }
        set { SetValue(HeaderProperty, value); }
    }

    public static readonly DependencyProperty HeaderProperty =
        DependencyProperty.Register("Header", typeof(FrameworkElement), typeof(Grid));
}

Feito isso, criei um estilo para que pudesse alterar a Template do ListBox:

<Style x:Key="ListBoxComHeader"
       TargetType="{x:Type ctl:MeuListBox}">
    <Setter Property="HorizontalContentAlignment"
            Value="Stretch" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ctl:MeuListBox}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <Border Grid.Column="0"
                            Width="{Binding ElementName=Items, Path=ActualWidth}">
                        <ContentPresenter Margin="2,0,0,0"
                                          Content="{Binding Path=Header, RelativeSource={RelativeSource TemplatedParent}}" />
                    </Border>
                    <ScrollViewer Grid.Row="1"
                                  CanContentScroll="False"
                                  Name="scroll"
                                  Focusable="false"
                                  Padding="{TemplateBinding Padding}">
                        <ItemsPresenter Name="Items"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Como podemos ver no código acima, coloquei um Grid, esse Grid possui duas linhas, na primeira linha coloquei uma borda definindo a largura de acordo com a propriedade ActualWidth do controle Items (ItemsPresenter – itens do ListBox) e, dentro dessa, um ContentPresenter, sendo que seu conteúdo está fazendo Binding com a propriedade Header (DependencyProperty) que criei na minha classe MeuListBox. Nesse ContentPresenter defini a margem como 2,0,0,0 para que os itens ficassem alinhados ao Header.
Já na segunda linha, temos um ScrollViewer e dentro dele temos o ItemsPresenter.
Depois disso feito, devemos agora aplicar o estilo no nosso ListBox e definir a propriedade Header:

<ctl:MeuListBox x:Name="listBox1"
                Margin="5"
                Style="{StaticResource ListBoxComHeader}">
    <ctl:MeuListBox.Header>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="100" />
                <ColumnDefinition Width="300" />
                <ColumnDefinition Width="100" />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0"
                       Text="Nome"
                       FontWeight="Bold"
                       HorizontalAlignment="Left"
                       Foreground="Black" />
            <TextBlock Grid.Column="1"
                       Text="Idade"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
            <TextBlock Grid.Column="2"
                       Text="Cidade"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
            <TextBlock Grid.Column="3"
                       Text="Estado"
                       FontWeight="Bold"
                       HorizontalAlignment="Center"
                       Foreground="Black" />
        </Grid>
    </ctl:MeuListBox.Header>
    <ctl:MeuListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="300" />
                    <ColumnDefinition Width="100" />
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Column="0"
                           Text="{Binding Nome}"
                           HorizontalAlignment="Left"
                           Foreground="Black" />
                <TextBlock Grid.Column="1"
                           Text="{Binding Idade}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
                <TextBlock Grid.Column="2"
                           Text="{Binding Cidade}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
                <TextBlock Grid.Column="3"
                           Text="{Binding Estado}"
                           HorizontalAlignment="Center"
                           Foreground="Black" />
            </Grid>
        </DataTemplate>
    </ctl:MeuListBox.ItemTemplate>
</ctl:MeuListBox>

Se observarmos, no Header temos um Grid contendo quatro colunas, e claro, no ItemTemplate também temos um Grid com as mesmas quatro colunas, ou seja, a estrutura do Header deve ser exatamente a mesma do ItemTemplate para que as colunas fiquem alinhadas.

Abaixo, podemos ver o resultado final:

 

Como pudemos ver no exemplo acima, para que todos os nossos ListBoxes tenham Header basta definirmos o estilo e também a propriedade Header.

Como no Header podemos colocar qualquer controle, podemos colocar botões, checkbox, etc.

Abaixo, segue projeto, o mesmo está nomeado como ListBoxSample.doc, favor renomear para .zip, pois não consigo anexar arquivos .zip no WordPress.
ListBox Sample

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s


%d blogueiros gostam disto: