locked
Custom DependencyProperty works but DoubleAnimation does not work. RRS feed

  • Question

  • <Page
        x:Class="Test.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MarginTest"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
        <Page.Resources>
            <Storyboard x:Name="FlyStoryBoard">
                <DoubleAnimation Storyboard.TargetName="RedSquare"
                                 Storyboard.TargetProperty="FlyLeft"
                                 From="0" To="100"
                                 Duration="0:0:10"/>
            </Storyboard>
        </Page.Resources>

        <Canvas Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
            <local:FlyCanvas x:Name="RedSquare" Canvas.Left="100" Canvas.Top="100" Background="Red" Width="96" Height="96" FlyLeft="12"  ></local:FlyCanvas>
            <Button Content="Move" Canvas.Left="10" Canvas.Top="50" Click="ButtonBase_OnClick" ></Button>
        </Canvas>
    </Page>

    namespace Test
    {
        public class FlyCanvas : Canvas
        {
            public static readonly DependencyProperty FlyLeftProperty =
             DependencyProperty.Register("FlyLeft", typeof(double), typeof(FlyCanvas), new PropertyMetadata(0.0, OnFlyLeftPropertyChanged));

            static void OnFlyLeftPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
            {
                FlyCanvas sender = (FlyCanvas)source;
                if (sender == null)
                    return;
                sender.OnFlyLeftChanged(args);
            }

            private void OnFlyLeftChanged(DependencyPropertyChangedEventArgs args)
            {
                // it gets here. It works, but not with Animation
                int x = 0;
            }

            public double FlyLeft
            {
                get { return (double)GetValue(FlyLeftProperty); }
                set { SetValue(FlyLeftProperty, value); }
            }
        }
    }

    namespace Test
    {
        /// <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();
            }

            private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
                Storyboard sb = (Storyboard)this.Resources["FlyStoryBoard"];
                if (sb != null)
                    sb.Begin();
            }
        }
    }

    Everything works fine, but with StoryBoard it never hit that break point. Why? Here I would like to place my code for flying. The DoubleAnimation is to change double value but it is not working, but no error either. It is complete code.

    Any Clue?

    Best regards

    Agha


    Agha Khan

    Thursday, January 16, 2014 5:47 AM

Answers

All replies

  • Hi Agha,

    of course it doesn't work, because your FlyCanvas is arranged inside of a Canvas, and the Canvas itself doesn't know anything about your FlyLeft-Property. Instead you should change the Canvas.Left-Property to animate it. That means you've two options:

    1. Just change your FlyLeft-PropertyEventhandler as below

        private void OnFlyLeftChanged(DependencyPropertyChangedEventArgs args)
                {
                    // it gets here. It works, but not with Animation
                    this.SetValue(Canvas.LeftProperty, args.NewValue);
                }

    The question is then, why you need that FlyLeft-Property at all. Why create a Canvas-subclass at all and not just use a Rectangle.

    2. Adjust your Storyboard to directly animate Canvas.Left instead of the FlyLeft-Property. That would be great:

       <Storyboard x:Key="FlyStoryBoard">
                <DoubleAnimation Storyboard.TargetName="RedSquare"
                                  Storyboard.TargetProperty="(Canvas.Left)"
                                  From="0" To="100"
                                  Duration="0:0:10"/>
            </Storyboard>


    Thomas Claudius Huber

    "If you can't make your app run faster, make it at least look & feel extremly fast"

    My latest app: The "Womanizer" :-)
    twitter: @thomasclaudiush
    homepage: www.thomasclaudiushuber.com
    author of: ultimate Windows Store Apps handbook | ultimate WPF handbook | ultimate Silverlight handbook

    Thursday, January 16, 2014 6:12 AM
  • First of all thanks for reply. I think you misunderstood the question.

    My object is not to move left or right but maybe rotation and some type of transformation, but put a break point and I should hit a break point which I never did. My question was how I can hit the break point. In real sense StortBoard is nothing than a timer thread which hides informing the UI thread. If you place FlyLeft=Any value in XAML file you will hit the break point. This implies it works, but when do with Storyboard it does not. Why?  Again thanks for reply.

    Best regards

    Agha Khan

     


    Agha Khan

    Thursday, January 16, 2014 6:25 AM
  • Hi,

    FlyLeftProperty is the DependencyProperty which your described in your project. But does the property value can affect the the FlyCanvas's appearance. For example, the Backgroundproperty can affect the cavans background color, the heightproperty can affect the cavans size. I think the FlyLeftProperty you described cannot change the FlyCanvas's UI, so the animation cannot play.

    Best Wishes!


    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. Thanks<br/> MSDN Community Support<br/> <br/> Please remember to &quot;Mark as Answer&quot; the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    Friday, January 17, 2014 2:30 AM
  • Dear Anne Jing:I don't think so unless you have a valid reason. This is not correct either (I can not change canvas behavior else then why we have those prosperities)  because I can rotate the Square any value if I place any value in XAML and it works well. I am afraid it is not a correct answer. DoubleAnimation means it is going to change double value and it is general type of DependencyProperty with no special attribute and now you are suggesting me that no custom DependencyProperty can be animated.            Best regards    Agha Khan

    Agha Khan

    Friday, January 17, 2014 3:32 AM
  • Dear Anne Jing: (Here is whole code which works in Silverlight, but not working in WinRT)

    Why it is not working in WinRT?

    <UserControl x:Class="ThicknessAnimation.MainPage"
        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"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:local="clr-namespace:ThicknessAnimation"
        mc:Ignorable="d"
        d:DesignHeight="300" d:DesignWidth="400">

        <Canvas x:Name="LayoutRoot" Background="White">
            <Canvas.Resources>
                <Storyboard x:Key="animation">
                    <DoubleAnimation Storyboard.TargetName="rect" Storyboard.TargetProperty="Value" From="0" To="100" Duration="00:00:1"></DoubleAnimation>
                </Storyboard>
            </Canvas.Resources>
            <Button Content="Click to animate" Width="140" Height="40"  Click="Button_Click" Canvas.Left="180" Canvas.Top="180"></Button>
            <local:RedCanvas x:Name="rect" HorizontalAlignment="Left"  VerticalAlignment="Top" CanFly="FlyUSA" />
        </Canvas>
    </UserControl>

    namespace ThicknessAnimation
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
            }

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                Storyboard sb = ((Storyboard)LayoutRoot.Resources["animation"]);
                if (sb != null)
                    sb.Begin();
            }
        }
    }

    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;

    namespace ThicknessAnimation
    {
        public class RedCanvas : Canvas
        {
            public RedCanvas()
            {
               Background = new SolidColorBrush(Colors.Red);
                Width = 50;
                Height = 50;
            }

            public String CanFly
            {
                get{return (String)GetValue(PropertyNameProperty);}
                set{SetValue(PropertyNameProperty, value);}
            }

            // Using a DependencyProperty as the backing store for PropertyName.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty PropertyNameProperty =
                DependencyProperty.Register("CanFly", typeof(String), typeof(RedCanvas), new PropertyMetadata("FlyUSA"));

            public double Value
            {
                get{return (double)GetValue(ValueProperty);}
                set{SetValue(ValueProperty, value);}
            }

            // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ValueProperty =
                DependencyProperty.Register("Value", typeof(double), typeof(RedCanvas), new PropertyMetadata(0.0, OnValueChanged));


            static void OnValueChanged(DependencyObject source, DependencyPropertyChangedEventArgs args)
            {
                RedCanvas sender = (RedCanvas)source;
                if (sender != null)
                    sender.UpdateMargin();
            }

            private void UpdateMargin()
            {// Here it should not be only Margin. You may have it whatever you like 
                var nextThickness = new Thickness(Value, Value, 0, 0);
                Margin = nextThickness;
            }
        }
    }

     

    Agha Khan

    Saturday, January 18, 2014 2:46 AM
  • Animations that affect the layout can hurt performance and are disabled by default. You can turn them on by enabling dependent animations, but a better choice would be to animate where the object renders with a RenderTransform rather than where it lays out.

    See Storyboarded animations for details, in particular Differences with Silverlight and WPF and Dependent and independent animations .

    Saturday, January 18, 2014 2:59 AM
    Moderator
  • Agha and I discussed this offline and confirmed that the problem was using a dependent animation without enabling them. Agha fixed the problem by switching to an independent animation to animate the RenderTransform.

    --Rob

    Tuesday, January 21, 2014 2:36 AM
    Moderator