WPF List Animation

I had previously created a blog post with a sample project that demonstrated some basic use of the DataTemplate in WPF. I have seen some pretty slick WPF apps (blu is a nice one), and I wanted to try and see how hard it would be to improve the demo and the DataTemplate with an animation that would fade and ease in new elements to the list.

I began with my previous code and started by changing my list of Employees to an ObservableCollection. This enumerable type provides notifications when items get added, removed, or when the list is refreshed. This should cause my UI to update each time I add a new element to my list. I also added a button and a simple event handler that adds a new element to the list each time it is clicked.

Here's the new code-behind for my window:

public partial class Window1 : Window
{
    private ObservableCollection<Employee> MyCollection;

    public Window1()
    {
        InitializeComponent();
        MyCollection=new ObservableCollection<Employee>();
        PersonItems.ItemsSource = MyCollection;
    }

    ObservableCollection<Employee> CreatePeople()
    {
        Employee person1 = new Employee()
        {
            Firstname = "John",
            Lastname = "Smith",
            Role = "Manager",
            Username = "JSmith"
        };
        return new ObservableCollection<Employee>() { person1};
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        Employee person = new Employee()
        {
            Firstname = "John",
            Lastname = "Smith",
            Role = "Manager",
            Username = "JSmith"
        };
        MyCollection.Insert(0,person);
    }
}

I played around with my DataTemplate in the Xaml code to try to get a simple animation when an element is added to the list. I achieved this by hooking in to the Border.Loaded event on my template. Soon after an element is added to the list, the Border.Loaded event should be triggered. On this event, I added a couple simple animations. One is an opacity animation to gently fade in the new element. The other animation is an animation on the border's height property – this causes an effect that makes it look like the new element is sliding into the list. It makes the addition of new elements look much smoother and isn't as jarring and abrupt as it would be without some kind of effect.

Here’s my final Xaml code:

<Window x:Class="WpfDataTemplates.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfDataTemplates="clr-namespace:WpfDataTemplates"
    Title="Employee Viewer" Height="440" Width="358" MaxWidth="350">
<Window.Resources>
    <DataTemplate DataType="{x:Type WpfDataTemplates:Employee}">
        <Border x:Name="MyBorder" 
                Background="White" 
                Margin="5,10,5,5" 
                BorderBrush="Gray" 
                BorderThickness="1" 
                CornerRadius="3"
                Width="300" 
                SnapsToDevicePixels="True">
            <Border.BitmapEffect>
                <DropShadowBitmapEffect Color="Gray" 
                            Direction="0" 
                            Opacity="0.5" 
                            ShadowDepth="1" 
                            Softness="1" Noise="0.5"/>
            </Border.BitmapEffect>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="80"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="90"/>
                    <ColumnDefinition Width="200"/>
                </Grid.ColumnDefinitions>
                    <Image Width="60" 
                   Height="60" 
                   Grid.Column="0" 
                   Source="Resources\User.png"/>
                    <StackPanel Orientation="Vertical" 
                    Grid.Column="1">
                    <TextBlock Text="{Binding Path=Username}" 
                       FontSize="16" 
                       FontWeight="Bold" 
                       Foreground="Gray"/>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Name:"/>
                        <TextBlock Margin="5,0,0,0" 
                            Text="{Binding Path=Firstname}"/>
                        <TextBlock Margin="5,0,0,0" 
                            Text="{Binding Path=Lastname}"/>
                    </StackPanel>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="Role:"/>
                        <TextBlock Margin="5,0,0,0"     
                           Text="{Binding Path=Role}" 
                           FontWeight="Bold" 
                           Foreground="Black"/>
                    </StackPanel>
                </StackPanel>
            </Grid>
        </Border>
        <DataTemplate.Triggers>
            <EventTrigger RoutedEvent="Border.Loaded">
                <BeginStoryboard>
                    <Storyboard Name="ItemLoad">
                        <DoubleAnimation 
                            Storyboard.TargetProperty="(Border.Opacity)" 
                            From="0.0" To="1" Duration="0:0:1" />
                        <DoubleAnimation 
                            Storyboard.TargetProperty="(Border.Height)" 
                            From="0" To="100" Duration="0:0:0.25" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
            <Trigger Property="IsMouseOver" 
                     Value="True">
                <Setter Property="BorderBrush" 
                        TargetName="MyBorder" 
                        Value="LightBlue"/>
            </Trigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</Window.Resources>
<StackPanel Orientation="Vertical" 
            Height="Auto">
    <Label Content="Employees:" 
            FontSize="16" 
            FontWeight="Bold" 
           Foreground="Gray" 
           FontFamily="Century Gothic"/>
    <ScrollViewer Height="320">
        <ItemsControl x:Name="PersonItems" 
                  HorizontalAlignment="Left">
        </ItemsControl>
    </ScrollViewer>
        <Button Height="35" 
            Name="button1" 
            Width="85" 
            Click="button1_Click"
            Content="Add"/>
    </StackPanel>
</Window>

I’m fairly happy with the result – as this effect was fairly simple to achieve, and I think it would really come in handy in a UI with a list that is frequently updated..

You can download the source Visual Studio project here

Comments...

Like to leave a comment ?


Title

Comment

Name