locked
Animate object with no name

    Question

  • I'm trying to animate some dynamic objects in an itemcontrol.  I would like to animate the width and height so that when the user clicks one, it gets bigger to display more information.  The number and data of each is tied to a itemssource, so there is no way to name each object.  I can't find a way to animate without the name, but can't bind the name.

    Here is the xaml:

    <ItemsControl x:Name="gridNotify" Visibility="Visible" Margin="0" ItemsSource="{Binding Notify}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Vertical"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Border BorderBrush="#FF0f3663" Tag="{Binding ID}" BorderThickness="1,1,0,1" Width="55" Height="60" VerticalAlignment="Top" HorizontalAlignment="Right" Padding="5" 
                                    Background="#FFFFFF" Margin="0,10,0,0" Tapped="AnimateNotify">
                                <StackPanel Orientation="Vertical">
                                    <StackPanel Orientation="Horizontal">
                                        <Image Source="{Binding Image}" Opacity="1" Stretch="Uniform" Width="48" VerticalAlignment="Top"/>
                                        <StackPanel Orientation="Vertical" Margin="10,0,0,0">
                                            <TextBlock Text="{Binding Title}" Style="{StaticResource OzNotifyTitle}" Margin="0,3,0,0" HorizontalAlignment="Left"/>
                                            <TextBlock Text="{Binding Help}" Style="{StaticResource OzText}" Margin="10,5,0,0"/>
                                            <Border BorderBrush="Red" BorderThickness="1" CornerRadius="5" Padding="5" Tapped="DismissNotify" Margin="0,10,0,0" HorizontalAlignment="Left">
                                                <StackPanel Orientation="Vertical">
                                                    <TextBlock Text="Dismiss" Style="{StaticResource OzText}"/>
                                                </StackPanel>
                                            </Border>
                                        </StackPanel>
                                    </StackPanel>
                                </StackPanel>
                            </Border>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

    In the tapped event I would like to start an animation instead of just changing the width and height:

    Private Sub AnimateNotify(sender As Object, e As TappedRoutedEventArgs)
            Dim brd As Border = TryCast(sender, Border)
            If brd.Width = 55 Then
                ' animate out
                brd.Width = 320
                brd.Height = 120
            Else
                ' animate in?  go to object?
                brd.Width = 55
                brd.Height = 60
            End If
        End Sub

    I've tried putting a storyboard animation is xaml, then setting the TargetPropertyName to the border name but that breaks (name is blank, was hoping a name would be auto-generated).  I can't find a way to animate this!


    Thursday, April 9, 2015 4:58 PM

Answers

  • Thanks for the post, I could not get it to work...but I've never used blend.  But anyways, I did get it to work using code behind and creating a storyboard.

    This is exactly what I tried to do before, but I did not have "EnableDependentAnimation" set to true.  I'm not entirely sure what that does, but without it will not work.

    Here is the code:

    Dim brd As Border = TryCast(sender, Border)
            Dim duration As New Duration(TimeSpan.FromSeconds(0.2))
            Dim myWidth As New DoubleAnimation()
            Dim myHeight As New DoubleAnimation()
            myWidth.Duration = duration
            myHeight.Duration = duration
            Storyboard.SetTarget(myWidth, brd)
            Storyboard.SetTarget(myHeight, brd)
            Storyboard.SetTargetProperty(myWidth, "Width")
            Storyboard.SetTargetProperty(myHeight, "Height")
            If brd.Width = 55 Then
                ' animate out
                'brd.Width = 320
                'brd.Height = 120
                myWidth.To = 320
                myHeight.To = 120
            Else
                ' animate in?  go to object?
                'brd.Width = 55
                'brd.Height = 60
                myWidth.To = 55
                myHeight.To = 60
            End If
            myWidth.EnableDependentAnimation = True
            myHeight.EnableDependentAnimation = True
            Dim sb As New Storyboard
            sb.Duration = duration
            sb.Children.Add(myWidth)
            sb.Children.Add(myHeight)
            sb.Begin()

    • Marked as answer by Jacob2014 Friday, April 10, 2015 6:46 PM
    Friday, April 10, 2015 6:46 PM

All replies

  • I had exactly the same problem recently.

    What you can do is implement a storyboard animation within the DataTemplate. It is best to do this with Blend. It's not as difficult as it seems, but it does look complicated in the code I'll post below...

    Note: this is my XAML code for an animated user control that I use to populate a GridView. The storyboard code was generated in Blend, so I strongly recommend you do the same. Just be careful that you are animating the DataTemplate, not the ItemScontrol itself (Blend can be a bit weird to get used to). My code can't be pasted into yours, but it should demonstrate one way of solving your problem.

    <UserControl
        x:Class="Match.FlippableCard"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Match"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="100"
        d:DesignWidth="100">
    
      <Grid x:Name="TopGrid" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10" Width="{Binding CardSize}" Height="{Binding CardSize}">
        <Grid.Resources>
          <Storyboard x:Name="CardFlipUp">
            <DoubleAnimation Duration="0:0:0.1" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.SkewX)" Storyboard.TargetName="grid" d:IsOptimized="True" />
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)" Storyboard.TargetName="grid">
              <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="1" />
              <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0.0" />
              <EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="1" />
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="CardFront">
              <DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Collapsed</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
              <DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="textBlock">
              <DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Collapsed</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
              <DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="textBlock1">
              <DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Collapsed</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
              <DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Visible</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="CardBack">
              <DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                <DiscreteObjectKeyFrame.Value>
                  <Visibility>Collapsed</Visibility>
                </DiscreteObjectKeyFrame.Value>
              </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
          </Storyboard>
        </Grid.Resources>
        <Grid x:Name="SecondGrid" Background="{Binding Colour}">
          <Grid x:Name="grid" Width="{Binding CardSize}" Height="{Binding CardSize}" RenderTransformOrigin="0.5,0.5">
            <Grid.RenderTransform>
              <CompositeTransform />
            </Grid.RenderTransform>
            <Image x:Name="CardFront" Source="{Binding Image}" Width="{Binding CardSize}" />
            <TextBlock x:Name="textBlock" Text="{Binding Name}" RenderTransformOrigin="0,0" HorizontalAlignment="Left" FontFamily="Resources/Fonts/Bangers.ttf#Bangers" VerticalAlignment="Top" />
            <TextBlock x:Name="textBlock1" Text="{Binding Name}" RenderTransformOrigin="0,0" FontFamily="Resources/Fonts/Bangers.ttf#Bangers" HorizontalAlignment="Right" VerticalAlignment="Bottom" />
            <Image x:Name="CardBack" Source="/Images/Cards/cardBack.png" Width="{Binding CardSize}" Stretch="Fill" />
            <Image Source="/Images/Cards/black.png" Visibility="{Binding IsLive, Converter={StaticResource BoolToVisConverterReverse}}" Stretch="Fill" Width="{Binding CardSize}" Height="{Binding CardSize}" />
          </Grid>
        </Grid>
      </Grid>
    </UserControl>

    My DataTemplate is just the above UserControl:

    <DataTemplate x:Key="CardTemplateFullSize">
            <local:FlippableCard Show="{Binding Path=Show, Mode=OneWay}" GridSize="100" />
    </DataTemplate>

    To run the animation I just call the storyboard by name on the item (in this case I have a reference to the item that was clicked just like you are doing with 'brd'.

    Something like brd.CardFlipUp.Begin();

    I hope that solves your issue. If not, let me know.


    Visit http://blog.grogansoft.com/ for Windows development fun.

    Thursday, April 9, 2015 11:54 PM
  • Thanks for the post, I could not get it to work...but I've never used blend.  But anyways, I did get it to work using code behind and creating a storyboard.

    This is exactly what I tried to do before, but I did not have "EnableDependentAnimation" set to true.  I'm not entirely sure what that does, but without it will not work.

    Here is the code:

    Dim brd As Border = TryCast(sender, Border)
            Dim duration As New Duration(TimeSpan.FromSeconds(0.2))
            Dim myWidth As New DoubleAnimation()
            Dim myHeight As New DoubleAnimation()
            myWidth.Duration = duration
            myHeight.Duration = duration
            Storyboard.SetTarget(myWidth, brd)
            Storyboard.SetTarget(myHeight, brd)
            Storyboard.SetTargetProperty(myWidth, "Width")
            Storyboard.SetTargetProperty(myHeight, "Height")
            If brd.Width = 55 Then
                ' animate out
                'brd.Width = 320
                'brd.Height = 120
                myWidth.To = 320
                myHeight.To = 120
            Else
                ' animate in?  go to object?
                'brd.Width = 55
                'brd.Height = 60
                myWidth.To = 55
                myHeight.To = 60
            End If
            myWidth.EnableDependentAnimation = True
            myHeight.EnableDependentAnimation = True
            Dim sb As New Storyboard
            sb.Duration = duration
            sb.Children.Add(myWidth)
            sb.Children.Add(myHeight)
            sb.Begin()

    • Marked as answer by Jacob2014 Friday, April 10, 2015 6:46 PM
    Friday, April 10, 2015 6:46 PM
  • EnableDependentAnimation is required because you're animating properties (Width and Height) which are expensive to animate. They are disabled by default, and in general you are better off animating the scale in a RenderTransform rather than the properties directly.

    See Dependent and independent animations in the Storyboarded animations documentation.

    Friday, April 10, 2015 7:23 PM
    Moderator