user6283344
user6283344

Reputation:

How to animate inserted objects in an ItemsControl with a slide-in animation?

After looking at several examples on this site it appears that the type of animation I wanted here is not that hard. Right now I've this in my xaml:

<ItemsControl ItemsSource="{Binding MyCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Name="Info">
                <TextBlock Text="{Binding ItemName}"/>
                <TextBlock Text="{Binding Quantity}"/>
                <TextBlock Text="{Binding Price}"/>
            </StackPanel>
            <DataTemplate.Resources>
                <Storyboard x:Key="Anim">
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Info" 
                                            Storyboard.TargetProperty="(UIElement.Opacity)">
                        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                        <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </DataTemplate.Resources>
            <DataTemplate.Triggers>
                <EventTrigger RoutedEvent="Loaded">
                    <BeginStoryboard Storyboard="{StaticResource Anim}" />
                </EventTrigger>
            </DataTemplate.Triggers>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

an in code, I'm adding last item in first place in this way:

MyCollection.Insert(0, new Transaction()
{
    Name = ItemName + "   ",
    Quantity = QuantityTraded, 
    Price = AtPrice
});

With all these new item fades in on the left corner and pushes all existing items to the right BUT the behavior is snappy! I want a translate instead of opacity and for that I've to have this in StackPanel inside DataTemplate:

<StackPanel.RenderTransform>
    <TransformGroup>
        <TranslateTransform/>
    </TransformGroup>
</StackPanel.RenderTransform>

What do I have to have in Storyboard for TranslateTransform? Will it animate all existing items or those will snap to their target position as they do with these code?

I've tried with blend which inserted these:

<b:Interaction.Behaviors>
    <b:FluidMoveBehavior Duration="0:0:5" AppliesTo="Children">
        <b:FluidMoveBehavior.EaseY>
            <BackEase EasingMode="EaseOut"/>
        </b:FluidMoveBehavior.EaseY>
        <b:FluidMoveBehavior.EaseX>
            <BackEase EasingMode="EaseIn"/>
        </b:FluidMoveBehavior.EaseX>
    </b:FluidMoveBehavior>
</b:Interaction.Behaviors>

inside ItemsControl but that didn't change the behavior!

Upvotes: 0

Views: 424

Answers (1)

Corentin Pane
Corentin Pane

Reputation: 4943

As a starting point, you could animate the Width property of the StackPanel from 0 to its maximum width. This will indeed push all items to the right as the first item grows.

<Storyboard x:Key="Anim">
    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Info" 
                        Storyboard.TargetProperty="Width">
        <EasingDoubleKeyFrame KeyTime="0" Value="0" />
        <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="100" />
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

enter image description here

But animating the Width might not be the visual effect you intend.

You could elaborate on that and instead animate the Width of an outer element that will crop your inner StackPanel:

<DataTemplate>
    <StackPanel x:Name="Outer" Margin="5">
        <StackPanel x:Name="Info" Orientation="Vertical" HorizontalAlignment="Right" Width="50">
            <TextBlock Text="{Binding ItemName}"/>
            <TextBlock Text="{Binding Quantity}"/>
            <TextBlock Text="{Binding Price}"/>
        </StackPanel>
    </StackPanel>
    <DataTemplate.Resources>
        <Storyboard x:Key="Anim">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Outer" 
                                           Storyboard.TargetProperty="Width">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="50" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </DataTemplate.Resources>
    <DataTemplate.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard Storyboard="{StaticResource Anim}" />
        </EventTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

enter image description here

You might have to do some adjustments from here to remove any hardcoded values in the animations.

Upvotes: 1

Related Questions