Wrapped List Box - Rudi Grobler
Tuesday, July 31, 2007 8:11 PM rudi

Wrapped List Box

WPF provides look less controllers witch makes it very easy to modify control look and behaviours. To demo how powerful this feature is, I will modify the standard list box to rather use a wrap panel and not the standard stack panel. This will make all the items in the list box be displayed from left to right. Once it riches the end, then thy wrap to the next line. To test this, resize your window to determine how thy wrap. This type of wrap behaviour is very commonly used when displaying products or photos.

Start a new WPF project and add a standard list box to the grid. Set this list box to have 0 margins to consume the whole screen.  Also add some dummy list box items or bind the list box to actual data.

<Grid x:Name="LayoutRoot">
       <
ListBox Margin="0,0,0,0" IsSynchronizedWithCurrentItem="True">
              <
ListBoxItem Content="Dummy #1" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #2" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #3" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #4" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #5" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #6" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #7" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #8" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #9" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #10" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #11" Width="100" Height="100"/>
              <
ListBoxItem Content="Dummy #12" Width="100" Height="100"/>
       </
ListBox>
</
Grid>

Next, we need to add a style to convert the stack panel to a wrap panel

<Style x:Key="WrapListBoxStyle" TargetType="{x:Type ListBox}">
       <
Setter Property="Template">
              <
Setter.Value>
                     <
ControlTemplate TargetType="{x:Type ListBox}">
                           <
WrapPanel Width="Auto" Height="Auto" IsItemsHost="True"/>
                     </
ControlTemplate>
              </
Setter.Value>
       </
Setter>
</
Style>

Add the following Style to the <Window.Resources> section

Next, we need to add a style to handle list box item selection. If you need to modify how the item gets selected or highlighted, this is where you would change that...

<Style x:Key="WrapItemStyle" TargetType="{x:Type ListBoxItem}">
       <
Setter Property="HorizontalContentAlignment" Value="Center"/>
       <
Setter Property="VerticalContentAlignment" Value="Center"/>
       <
Setter Property="Template">
              <
Setter.Value>
                     <
ControlTemplate TargetType="{x:Type ListBoxItem}">
                           <
Border SnapsToDevicePixels="true" x:Name="Bd" Width="100" Height="100" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
                                  <
ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                           </
Border>
                           <
ControlTemplate.Triggers>
                                  <
Trigger Property="IsSelected" Value="true">
                                         <
Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                                         <
Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
                                  </
Trigger>
                                  <
MultiTrigger>
                                         <
MultiTrigger.Conditions>
                                                <
Condition Property="IsSelected" Value="true"/>
                                                <
Condition Property="Selector.IsSelectionActive" Value="false"/>
                                         </
MultiTrigger.Conditions>
                                         <
Setter Property="Background" TargetName="Bd" value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
                                         <
Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                                  </
MultiTrigger>
                           </
ControlTemplate.Triggers>
                     </
ControlTemplate>
              </
Setter.Value>
       </
Setter>
</
Style>

Lastly, we need to update our list box and list box items to use the dynamic resources

<ListBox Margin="0,0,0,0" Style="{DynamicResource WrapListBoxStyle}" IsSynchronizedWithCurrentItem="True">
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #1" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #2" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #3" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #4" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #5" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #6" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #7" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #8" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #9" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #10" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #11" Width="100" Height="100"/>
       <
ListBoxItem Style="{DynamicResource WrapItemStyle}" Content="Dummy #12" Width="100" Height="100"/>
</
ListBox>

And that is all that is required to convert a stock standard list box into a flashy wrapped list box

Filed under:

Comments

# re: Wrapped List Box

Tuesday, July 31, 2007 9:31 PM by rudi

Currently I set the ControlTemplate, to change to a wrap panel but the correct way is actually to change the ListBox.ItemsPanel of type ItemsPanelTemplate to be a wrap panel.