WPF Reflections

Nov 14 2007   2:03PM GMT

ListBox - multi column example



Posted by: Mark Shurmer
WPF
A listbox can easily be used as a multi-column list in WPF. To do that, you need firstly, a listbox:

<Listbox x:Name=”lbFields” IsSynchronizedWithCurrentItem=”True” ItemsSource=”{Binding Path=blah}” >

Then, you need to define a couple of templates, one for the headers and one for the items to be drawn. The header one needs to style the buttons that you will use to action header clicking:

<ControlTemplate x:Key=”Header” TargetType=”{x:Type Button}”>
  <Border Background=”Silver” TextBlock.Foreground=”White” TextBlock.FontSize=”10″      Padding=”10,3,10,4″>
  <ContentPresenter/>
  </Border>
  </ControlTemplate>

Then the template for the items, i’m using a custom object with 4 properties, but it can be anything of course:

<DataTemplate x:Key=”readonlyColInfo”>
  <Grid ShowGridLines=”True” >
  <Grid.ColumnDefinitions>
  <ColumnDefinition Width=”Auto” SharedSizeGroup=”NameColumn”/>
  <ColumnDefinition Width=”Auto” SharedSizeGroup=”WidthColumn”/>
  <ColumnDefinition Width=”Auto” SharedSizeGroup=”AutoFitColumn”/>
  <ColumnDefinition Width=”Auto” SharedSizeGroup=”VisibleColumn”/>
  </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="10,0,10,0" Text="{Binding Path=Name}"/>
  <TextBlock Grid.Column=”1″ Margin=”10,0,10,0″ Text=”{Binding Path=Width}”/>
  <TextBlock Grid.Column=”2″ Margin=”10,0,10,0″ Text=”{Binding Path=AutoFit}”/>
  <TextBlock Grid.Column=”3″ Margin=”10,0,10,0″ Text=”{Binding Path=Visible}” />
  </Grid>
  </DataTemplate>

Note, we use shared size grouping on the columns, that’s so that the grids containing the headers and the items size the same.
Then we need to apply these templates to the listbox, which we do via a style:

<Style x:Key=”{x:Type ListBox}” TargetType=”{x:Type ListBox}”>
  <Setter Property=”Template”>
    <Setter.Value>
  <ControlTemplate>
  <Grid>
  <Grid.RowDefinitions>
     <RowDefinition Height=”Auto”/>
     <RowDefinition Height=”*”/>
  </Grid.RowDefinitions>
<Border Grid.Row="1">
  <Border Margin=”10″ BorderThickness=”1″ BorderBrush=”Black”>
     <DockPanel Grid.IsSharedSizeScope=”True”>
        <ScrollViewer HorizontalScrollBarVisibility=”Hidden”             VerticalScrollBarVisibility=”Auto”             DockPanel.Dock=”Top”>
  <Grid DockPanel.Dock=”Top” Margin=”0,0,18,0″>
     <Grid.ColumnDefinitions>
      <ColumnDefinition Width=”Auto” SharedSizeGroup=”NameColumn”/>
      <ColumnDefinition Width=”Auto” SharedSizeGroup=”WidthColumn”/>
      <ColumnDefinition Width=”Auto” SharedSizeGroup=”AutoFitColumn”/>
      <ColumnDefinition Width=”Auto” SharedSizeGroup=”VisibleColumn”/>
    </Grid.ColumnDefinitions>
    <Button Grid.Column=”0″ Template=”{StaticResource Header}”> Name </Button>
    <Button Grid.Column=”1″ Template=”{StaticResource Header}” > Width </Button>
    <Button Grid.Column=”2″ Template=”{StaticResource Header}” > Auto fit </Button>
    <Button Grid.Column=”3″ Template=”{StaticResource Header}”> Visible </Button>
  </Grid>
  </ScrollViewer>
  <ScrollViewer HorizontalScrollBarVisibility=”Visible” Name=”Master”>
  <StackPanel IsItemsHost=”True”/>
  </ScrollViewer>
  </DockPanel>
  </Border>
  </Border>
  </Grid>
  </ControlTemplate>
  </Setter.Value>
  </Setter>
  </Style>

Comment on this Post


You must be logged-in to post a comment. Log-in/Register

DylanM  |   Jun 9 2008   11:01PM GMT

Let WPF do the work for you:


 

DylanM  |   Jun 9 2008   11:03PM GMT

It didn’t post my code, but you can use ListView and GridView to do the above in about 7 lines of code.


 



MarkWPF2  |   Jun 10 2008   12:46PM GMT

I was trying to show that you can achieve some of the display characteristics of a ListView with a ListBox - without any of the baggage.
The point is that ListBox doesn’t have as many features and is therefore faster in some circumstances.