Archive for the ‘Uncategorized’ Category.

An alternative ListBox

The ListBox in WPF is your friend. Very useful little control. Simple databinding and ItemTemplate:ing makes it bread and butter, at least for me. BUT, the old white-background-with-blue-background-selected-item style can be a bit dull.

So I did an alternative which looks, if not necessarily nicer at least different from the standard. With a little animation when an item is selected or deselected.

The result looks like this:

The XAML looks like this (below is the only code needed).


<Window x:Class="ListBoxWrapPanel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <XmlDataProvider x:Key="PeopleData">
            <x:XData>
                <People xmlns="">
                    <Person Name="John" />
                    <Person Name="Peter" />
                    <Person Name="Craig"  />
                    <Person Name="Roger"  />
                    <Person Name="Colin"  />
                    <Person Name="Rodney"  />
                    <Person Name="Nigel" />
                    <Person Name="Godfrey" />
                    <Person Name="Bo"  />
                    <Person Name="Michael"  />
                    <Person Name="Steven"  />
                    <Person Name="Brendan"  />
                </People >
            </x:XData>
        </XmlDataProvider>

        <LinearGradientBrush x:Key="SelectedBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#FFFFFF" />
            <GradientStop Offset="1" Color="#FFFAFAFA" />
        </LinearGradientBrush>

        <LinearGradientBrush x:Key="NotSelectedBrush" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Offset="0" Color="#DEEBFF" />
            <GradientStop Offset="1" Color="#FFFAFAFA" />
        </LinearGradientBrush>
        
        <DataTemplate x:Key="NameplateItemTemplate">
            <TextBlock 
                    HorizontalAlignment="Left"
                    VerticalAlignment="Center"
                    Margin="2"
                    Height="18"
                    Text="{Binding XPath=@Name}"/>
        </DataTemplate>

        <Style x:Key="SelectedItemContainer" TargetType="{x:Type ListBoxItem}">
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="FocusVisualStyle" Value="{x:Null}" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListBoxItem}">
                        <Border 
                                Background="{StaticResource NotSelectedBrush}"
                                CornerRadius="3"
                                BorderThickness="1"
                                BorderBrush="LightGray"
                                x:Name="ContainerBorder"
                                Width="80"
                                Margin="4" >
                            <Border.Effect>
                                <DropShadowEffect 
                                    x:Name="dropShadow"
                                    BlurRadius="3"
                                    ShadowDepth="0"
                                    Color="LightGray"
                                    />
                            </Border.Effect>
                            <Border.RenderTransform>
                                <TranslateTransform x:Name="ContainerBorderTransform"  />
                            </Border.RenderTransform>
                            <ContentPresenter />
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="true">

                                <Trigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard Duration="0:0:0.1">
                                            <DoubleAnimation
                                                    By="10"
                                                    Storyboard.TargetName="dropShadow"
                                                    Storyboard.TargetProperty="ShadowDepth">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                            <DoubleAnimation
                                                    By="-10"
                                                    Storyboard.TargetName="ContainerBorderTransform"
                                                    Storyboard.TargetProperty="X">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                            <DoubleAnimation
                                                    By="-10"
                                                    Storyboard.TargetName="ContainerBorderTransform"
                                                    Storyboard.TargetProperty="Y">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.EnterActions>
                                <Trigger.ExitActions>
                                    <BeginStoryboard>
                                        <Storyboard Duration="0:0:0.1">
                                            <DoubleAnimation
                                                    By="-10"
                                                    Storyboard.TargetName="dropShadow"
                                                    Storyboard.TargetProperty="ShadowDepth">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                            <DoubleAnimation
                                                    By="10"
                                                    Storyboard.TargetName="ContainerBorderTransform"
                                                    Storyboard.TargetProperty="X">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                            <DoubleAnimation
                                                    By="10"
                                                    Storyboard.TargetName="ContainerBorderTransform"
                                                    Storyboard.TargetProperty="Y">
                                                <DoubleAnimation.EasingFunction>
                                                    <CircleEase EasingMode="EaseOut"/>
                                                </DoubleAnimation.EasingFunction>
                                            </DoubleAnimation>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </Trigger.ExitActions>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    
    <ListBox ItemsSource="{Binding Source={StaticResource PeopleData},XPath=//Person}"
             ItemContainerStyle="{StaticResource SelectedItemContainer}"
             ItemTemplate="{StaticResource NameplateItemTemplate}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel IsItemsHost="True"  Width="400" />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
</Window>