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








































