Tuesday, November 02, 2010

Timeline – or restyling controls

One nice thing with WPF that is slightly different is that the controls are lookless. This means that you can re-style or apply a different template altogether if the behavior of a standard control is what you want, but the looks are not.

A real world example: At work we recently needed to show a list of items with associated timestamps, in a way so that the time differences between them are easily determined at a glance.

Thanks to the lookless controls of WPF I was able to solve this simply by using a ListBox with re-templated ListBoxItems giving the following result:

image

The style is defined as follows:

        <Style TargetType="ListBoxItem" x:Key="TimelineStyle">
            <
Setter Property="SnapsToDevicePixels" Value="true"/>
            <
Setter Property="OverridesDefaultStyle" Value="true"/>
            <
Setter Property="FocusVisualStyle" Value="{x:Null}"/>
            <
Setter Property="Template">
                <
Setter.Value>
                    <
ControlTemplate TargetType="ListBoxItem">
                        <
StackPanel Orientation="Vertical"> <Border
                           
Name="Border"
                           
Padding="2"
                           
CornerRadius="2"
                           
BorderThickness="2"
                           
SnapsToDevicePixels="true">
                                <
ContentPresenter />
                            </
Border>
                            <
Grid>
                                <
Rectangle Width="2" Stroke="LightBlue"
                                          
Height="{Binding TimeToNext, Converter={StaticResource HeightConverter}}"
                                          
VerticalAlignment="Center"
                                          
HorizontalAlignment="Center"/>
                                <
TextBlock Text="{Binding TimeToNext, Converter={StaticResource DurationConverter}}"
                                          
Background="White"
                                          
VerticalAlignment="Center"
                                          
HorizontalAlignment="Center"
                                          
FontSize="8"
                                          
Foreground="Gray"/>
                            </
Grid>
                        </
StackPanel>
                        <
ControlTemplate.Triggers>
                            <
Trigger Property="IsSelected"
                                    
Value="true">
                                <
Setter TargetName="Border"
                                       
Property="BorderBrush"
                                       
Value="Blue"/>
                            </
Trigger>
                        </
ControlTemplate.Triggers>
                    </
ControlTemplate>
                </
Setter.Value>
            </
Setter>
        </
Style>

and and the listbox uses the style like this:

<ListBox ItemsSource="{Binding DataItems}" ItemContainerStyle="{StaticResource TimelineStyle}" />



The style uses two converters, but those should be fairly trivial.



Setting FocusVisualStyle to {x:Null} is done to hide the indication of keyboard focus, as unless it is fixed properly, will be more confusing than helpful. Fixing it properly is left as an exercise for the reader.

No comments: