Zach Olivare
Zach Olivare

Reputation: 4161

Converting UWP XAML animation to C#

I have a working XAML animation for animating an odometer-like digit. I need to make six almost identical, but different, versions of this animation. So far as I can tell there is not a nice way to reuse animation XAML in this way, so to keep the code DRY I turn to a programatic creation of the animation.

In trying to convert this XAML animation to C# I've run into an issue where my target can't be found:

No installed components were detected.\r\n\r\nCannot resolve TargetName Digit1.

If I call Storyboard.SetTarget() instead of Storyboard.SetTargetName() I no longer get this exception but still nothing happens on the screen.

Can someone tell me what I'm doing wrong in this translation?

XAML:

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d">

    <Page.Resources>
        <x:Double x:Key="OdometerMoveUpDistance">-101</x:Double>

        <Storyboard x:Name="OdometerUpStoryboard">
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
                                           Storyboard.TargetName="Digit1">
                <EasingDoubleKeyFrame KeyTime="0" Value="0" />
                <EasingDoubleKeyFrame KeyTime="0:0:1" Value="{StaticResource OdometerMoveUpDistance}" />
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Page.Resources>

    <Canvas x:Name="Odometer" Width="100" Height="100">
        <TextBlock x:Name="Digit1" FontSize="100" Text="8">
            <TextBlock.RenderTransform><CompositeTransform /></TextBlock.RenderTransform>
        </TextBlock>
    </Canvas>

</Page>

C#:

private void Btn_Click(object sender, RoutedEventArgs e)
{
    DoubleAnimationUsingKeyFrames digitUp = CreateOdometerdigitAnim(this.Digit1, 0, -101);

    var storyboard = new Storyboard();
    storyboard.Children.Add(digitUp);
    storyboard.Begin(); // Exception happens on this line
}

private DoubleAnimationUsingKeyFrames CreateOdometerdigitAnim(TextBlock digit, double startPos, double endPos)
{
    var start = new EasingDoubleKeyFrame();
    start.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0));
    start.Value = startPos;

    var end = new EasingDoubleKeyFrame();
    end.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(1000));
    end.Value = endPos;

    var anim = new DoubleAnimationUsingKeyFrames();
    anim.KeyFrames.Add(start);
    anim.KeyFrames.Add(end);

    Storyboard.SetTargetProperty(anim, "(UIElement.RenderTransform).(CompositeTransform.TranslateY)");
    Storyboard.SetTargetName(anim, digit.Name);

    /* Using SetTarget instead of SetTargetName throws no exception but still does not animate */
    // Storyboard.SetTarget(anim, digit);

    return anim;
}

Upvotes: 0

Views: 745

Answers (1)

Elvis Xia - MSFT
Elvis Xia - MSFT

Reputation: 10841

If I call Storyboard.SetTarget() instead of Storyboard.SetTargetName() I no longer get this exception but still nothing happens on the screen.

You need to give a CompositeTransform object to Digit1.RenderTransform. You can do it either in XAML or in code-behind:

If in XAML:

<TextBlock x:Name="Digit1" FontSize="100" Text="8">
    <TextBlock.RenderTransform>
        <CompositeTransform />
    </TextBlock.RenderTransform>
</TextBlock>

If in Code-Behind, add the codes before storyboard.Begin() like below:

Digit1.RenderTransform = new CompositeTransform();
...
storyboard.Begin();

In trying to convert this XAML animation to C# I've run into an issue where my target can't be found:

No installed components were detected.\r\n\r\nCannot resolve TargetName Digit1.

I can reproduce the problem with your codes. I tried it with a XAML defined StoryBoard+Animation, everything works fine. Need some confirmations through internal channel later.

Upvotes: 2

Related Questions