locked
Animating rectangle on Canvas question [Solved]

    Question

  • This has been solved ...

    For anyone interested I changed

    Storyboard.SetTargetProperty(anima1, "(UIElement.RenderTransform).(TranslateTransform.X)");

    to

    Storyboard.SetTargetProperty(anima1, "(Canvas.Left)");

    Hi,

    So I have a canvas with a couple of elements inside. I have a GridView and a rectangle. The gridview has some items in it and I just want to move the rectangle from one item to another. The problem I am having is that the animation seems to be moving the rectangle based on the coordinates of the WrapGrid inside my GridView instead of the coordinates of the Canvas. The WrapGrid is horizontally centered inside its parent. If I set the position of the rectangle using Canvas.SetLeft(rect1, x) then the rectangle gets positioned properly. Also, if I change the WrapGrid inside my GridView to have horizontalAlignment = "Left" then the animation will move to the correct location.

    My code behind has a couple of methods. "MainPage_Loaded" fires after the page is loaded and positions the rectangle at the first item in the grid (no problem there). "Canvas_KeyUp" targets the next item in the grid and sets up an animation to move the rectangle to that location. So the application loads with the rectangle properly positioned at the first item in the grid and then when I hit a key the rectangle moves too far to the right and passes the second item. It appears that it is moving to the coordinates based on the WrapGrid container instead of the Canvas.

    XAML

    <Page
        x:Class="FoodieMoiety.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:FoodieMoiety"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Page.Resources>
            <Style x:Key="GridViewItemStyle1" TargetType="GridViewItem">
                <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
                <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
                <Setter Property="Background" Value="Transparent"/>
                <Setter Property="TabNavigation" Value="Local"/>
                <Setter Property="IsHoldingEnabled" Value="True"/>
                <Setter Property="Margin" Value="0,0,2,2"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="GridViewItem">
                            <GridViewItemPresenter CheckHintBrush="{ThemeResource ListViewItemCheckHintThemeBrush}" CheckBrush="{ThemeResource ListViewItemCheckThemeBrush}" ContentMargin="4" ContentTransitions="{TemplateBinding ContentTransitions}" CheckSelectingBrush="{ThemeResource ListViewItemCheckSelectingThemeBrush}" DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}" DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}" DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}" DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" FocusBorderBrush="Black" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" PointerOverBackgroundMargin="1" PlaceholderBackground="Red" PointerOverBackground="Black" ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" SelectedPointerOverBorderBrush="Red" SelectionCheckMarkVisualEnabled="True" SelectedForeground="{ThemeResource ListViewItemSelectedForegroundThemeBrush}" SelectedPointerOverBackground="Red" SelectedBorderThickness="{ThemeResource GridViewItemCompactSelectedBorderThemeThickness}" SelectedBackground="Red" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Page.Resources>
    
    
        <Canvas x:Name="canvas" Width="1920" Height="1080" KeyUp="Canvas_KeyUp">
            <GridView x:Name="gridView1" Width="1920" Height="1080" CanReorderItems="True" BorderThickness="1" BorderBrush="Red" ItemContainerStyle="{StaticResource GridViewItemStyle1}" SelectionMode="Multiple">
                <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapGrid x:Name="wrapGrid1" Orientation="Horizontal" HorizontalAlignment="Center">
                            <WrapGrid.ChildrenTransitions>
                                <TransitionCollection>
                                    <ReorderThemeTransition />
                                </TransitionCollection>
                            </WrapGrid.ChildrenTransitions>
    
                        </WrapGrid>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>
            </GridView>
            <Rectangle x:Name="rect1" Height="259" Width="418" Opacity="1">
                <Rectangle.Fill>
                    <SolidColorBrush Color="Gray" Opacity="0"/>
                </Rectangle.Fill>
                <Rectangle.Stroke>
                    <SolidColorBrush Color="White" Opacity="1"/>
                </Rectangle.Stroke>
            </Rectangle>
        </Canvas>
    
    </Page>

    C#

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Diagnostics;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Media.Animation;
    
    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
    
    namespace FoodieMoiety
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
    
                for (int i = 0; i < 50; i++)
                {
                    Image img = new Image();
                    BitmapImage bitmapImage = new BitmapImage();
                    img.Width = bitmapImage.DecodePixelWidth = 400; //natural px width of image source
                    img.Height = bitmapImage.DecodePixelHeight = 250; //natural px width of image source
                    // don't need to set Height, system maintains aspect ratio, and calculates the other
                    // dimension, so long as one dimension measurement is provided
    
                    bitmapImage.UriSource = new Uri(this.BaseUri, "Assets/pic1.jpg");
                    img.Source = bitmapImage;
                    img.Margin = new Thickness(5);
    
                    gridView1.Items.Add(img);
                }
    
                this.Loaded += MainPage_Loaded;
            }
    
            async void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() =>
                {
                    var item = gridView1.ContainerFromIndex(0) as GridViewItem; //index 1 = second item
                    var gt = item.TransformToVisual(canvas);
                    Point point = gt.TransformPoint(new Point(0, 0));
                    double x = point.X;
                    Debug.WriteLine(x);
                    double y = point.Y;
                    Canvas.SetTop(rect1, y);
                    Canvas.SetLeft(rect1, x);
                }));
    
            }
    
            void Canvas_KeyUp(object sender, KeyRoutedEventArgs e)
            {
    
                var item = gridView1.ContainerFromIndex(1) as GridViewItem; //index 1 = second item
                var gt = item.TransformToVisual(canvas);
                Point point = gt.TransformPoint(new Point(0, 0));
                double x = point.X;
                Debug.WriteLine(x);
    
                //Canvas.SetLeft(rect1, x); 
    
                
                rect1.RenderTransform = new TranslateTransform();
                DoubleAnimation anima1 = new DoubleAnimation();
                anima1.Duration = TimeSpan.FromMilliseconds(1000);
                anima1.To = x;
    
                Storyboard.SetTarget(anima1, rect1);
                Storyboard.SetTargetProperty(anima1, "(UIElement.RenderTransform).(CompositeTransform.X)");
                Storyboard storyboard = new Storyboard();
                storyboard.Children.Add(anima1);
                storyboard.Begin();
                
    
    
            }
    
        }
    }

    Its a tough one I think. Thanks for your thoughts.

    Brian

    Edit: Sorry I forgot I was filling the grid with an image. I replaced that code to fill it with plain old rectangles so that you can easily load the code into a project and see what is going on ...

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Diagnostics;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.UI.Xaml.Media.Animation;
    using Windows.UI.Xaml.Shapes;
    
    // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
    
    namespace FoodieMoiety
    {
        /// <summary>
        /// An empty page that can be used on its own or navigated to within a Frame.
        /// </summary>
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
    
                for (int i = 0; i < 50; i++)
                {
                    /*
                    Image img = new Image();
                    BitmapImage bitmapImage = new BitmapImage();
                    img.Width = bitmapImage.DecodePixelWidth = 400; //natural px width of image source
                    img.Height = bitmapImage.DecodePixelHeight = 250; //natural px width of image source
                    // don't need to set Height, system maintains aspect ratio, and calculates the other
                    // dimension, so long as one dimension measurement is provided
    
                    bitmapImage.UriSource = new Uri(this.BaseUri, "Assets/pic1.jpg");
                    img.Source = bitmapImage;
                    img.Margin = new Thickness(5);
                    */
    
                    //gridView1.Items.Add(img);
                    Rectangle temp = new Rectangle();
                    temp.Width = 400;
                    temp.Height = 250;
                    SolidColorBrush blueBrush = new SolidColorBrush(Windows.UI.Colors.Blue);
                    temp.Fill = blueBrush;
                    gridView1.Items.Add(temp);
                }
    
                this.Loaded += MainPage_Loaded;
            }
    
            async void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new Windows.UI.Core.DispatchedHandler(() =>
                {
                    var item = gridView1.ContainerFromIndex(0) as GridViewItem; //index 1 = second item
                    var gt = item.TransformToVisual(canvas);
                    Point point = gt.TransformPoint(new Point(0, 0));
                    double x = point.X;
                    Debug.WriteLine(x);
                    double y = point.Y;
                    Canvas.SetTop(rect1, y);
                    Canvas.SetLeft(rect1, x);
                }));
    
            }
    
            void Canvas_KeyUp(object sender, KeyRoutedEventArgs e)
            {
    
                var item = gridView1.ContainerFromIndex(1) as GridViewItem; //index 1 = second item
                var gt = item.TransformToVisual(canvas);
                Point point = gt.TransformPoint(new Point(0, 0));
                double x = point.X;
                Debug.WriteLine(x);
    
                //Canvas.SetLeft(rect1, x);
    
                
                rect1.RenderTransform = new TranslateTransform();
                DoubleAnimation anima1 = new DoubleAnimation();
                anima1.Duration = TimeSpan.FromMilliseconds(1000);
                anima1.To = x;
    
                Storyboard.SetTarget(anima1, rect1);
                Storyboard.SetTargetProperty(anima1, "(UIElement.RenderTransform).(CompositeTransform.X)");
                Storyboard storyboard = new Storyboard();
                storyboard.Children.Add(anima1);
                storyboard.Begin();
                
    
    
            }
    
        }
    }

     



    • Edited by duffybr Wednesday, December 3, 2014 6:45 PM
    Tuesday, December 2, 2014 8:43 PM

Answers

  • This has been solved ...

    For anyone interested I changed

    Storyboard.SetTargetProperty(anima1, "(UIElement.RenderTransform).(TranslateTransform.X)");

    to

    Storyboard.SetTargetProperty(anima1, "(Canvas.Left)");

    Thanks for sharing your solution.

    Furthermore I think we could also let Blend generate the animation, the generated xaml code would help us write the animation C# code much easier.

    --James


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Tuesday, December 16, 2014 8:25 AM
    Moderator

All replies

  • Share your fully reproducbible sample with everyone then we can test for you instead of create from scratch

    Wednesday, December 3, 2014 8:33 AM
  • I'm not sure what you mean? I only have the xaml and c# code and I supplied those. I changed the c# code to use rectangles for gridviewItems instead of images a few minutes after I posted and shared that as well. Let me know what else you need
    Wednesday, December 3, 2014 1:08 PM
  • This has been solved ...

    For anyone interested I changed

    Storyboard.SetTargetProperty(anima1, "(UIElement.RenderTransform).(TranslateTransform.X)");

    to

    Storyboard.SetTargetProperty(anima1, "(Canvas.Left)");

    Thanks for sharing your solution.

    Furthermore I think we could also let Blend generate the animation, the generated xaml code would help us write the animation C# code much easier.

    --James


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Tuesday, December 16, 2014 8:25 AM
    Moderator