Ask a questionAsk a question
 

AnswerSplineDoubleKeyFrame set from DynamicResource

  • Monday, October 26, 2009 10:14 PMzaurska Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I want to use a dynamic resource to give the rotate transform angle to a SplineDoubleKeyFrame.  I've used dynamic resources to do this on a doubleAnimation.To

    I can set it in code behind if I reference the key by its index, if I do this instead:

                DoubleAnimationUsingKeyFrames 
                    daukf=(DoubleAnimationUsingKeyFrames)TryFindResource("thisOne");

                ((SplineDoubleKeyFrame)daukf.KeyFrames[0]).Value = 19;

    But this just makes me more curious as to why I can't do that in xaml.

    Can anyone tell me why this doesn't work?

    thanks

    <Window
    	xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    	xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    	x:Class="UntitledProject1.Window1"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
    	x:Name="Window"
    	Title="Window1"
    	Width="640" Height="480">
        
    
    	<Window.Resources>
    		
            <sys:Double x:Key="sdKey">18.545</sys:Double>
    
    			<DoubleAnimationUsingKeyFrames x:Key="thisOne" 
                       BeginTime="00:00:00" 
                       Storyboard.TargetName="rectangle" 
                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
    				<SplineDoubleKeyFrame KeyTime="00:00:0.5" Value="{DynamicResource sdKey}"/>
    			</DoubleAnimationUsingKeyFrames>
    
    	</Window.Resources>
    
    
    	<Grid x:Name="LayoutRoot">
    		<Rectangle Fill="#FFB70000" Stroke="#FF000000" 
    		HorizontalAlignment="Right" Margin="0,160,232,206" 
    		Width="80" RenderTransformOrigin="-3,0" x:Name="rectangle">
    			<Rectangle.RenderTransform>
    				<TransformGroup>
    					<ScaleTransform ScaleX="1" ScaleY="1"/>
    					<SkewTransform AngleX="0" AngleY="0"/>
    					<RotateTransform Angle="0"/>
    					<TranslateTransform X="0" Y="0"/>
    				</TransformGroup>
    			</Rectangle.RenderTransform>
    		</Rectangle>
            
            <Button Height="30" HorizontalAlignment="Right" Margin="0,44,42,0" Name="button1" VerticalAlignment="Top" Width="117" Click="button1_Click">Button</Button>
       
        </Grid>
    </Window>
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Windows.Media.Animation;
    
    namespace UntitledProject1
    {
    	/// <summary>
    	/// Interaction logic for Window1.xaml
    	/// </summary>
    	public partial class Window1 : Window
    	{
            Storyboard sb = new Storyboard();
    
    		public Window1()
    		{
    			this.InitializeComponent();
    	
    			// Insert code required on object creation below this point.
    		}
    
            private void button1_Click(object sender, RoutedEventArgs e)
            {
    
                 sb.Children.Add((DoubleAnimationUsingKeyFrames)TryFindResource("thisOne"));
                sb.Begin(this, true);
    
    
            }
    	}
    }
    

    • Edited byzaurska Monday, October 26, 2009 10:49 PMadditional info
    •  

Answers

  • Friday, October 30, 2009 9:13 AMLinda LiuMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi Zaurska,

    Using DynamicResource markup extensions in XAML equals to setting resource reference in code. For example:
    XAML
    <TextBlock Name="txtbox" Background="{DynamicResource myBrush}"/>

    code behind
    this.txtbox.SetResourceReference(TextBlock.BackgroundProperty, "myBrush");

    Note that only FrameworkElement or FrameworkContentElement or FrameworkElementFactory class has the SetResourceReference method. That's to say, we can only associate property with a resource on FrameworkElement or FrameworkContentElement or FrameworkElementFactory. The SplineDoubleKeyFrame is not any of above types, so it couldn't be associated with a resource, i.e. using DynamicResource on the SplineDoubleKeyFrame has no effect.

    Changing the "DynamicResource" to "StaticResource" in the XAML can solve the problem. For example:

    <DoubleAnimationUsingKeyFrames x:Key="thisOne"
                       BeginTime="00:00:00"
                       Storyboard.TargetName="rectangle"
                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
    <SplineDoubleKeyFrame KeyTime="00:00:0.5" Value="{StaticResource sdKey}"/>
    </DoubleAnimationUsingKeyFrames>


    Hope this helps.
    If you have any question, please feel free to let me know.

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
  • Monday, November 02, 2009 10:42 AMLinda LiuMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi Zaurska,

    You can bind the Value property of the SplineDoubleKeyFrame to a property of a business class. Change the value of the business class property at run time and the SplineDoubleKeyFrame.Value property will be changed. For example:

    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="UntitledProject1.Window1"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:UntitledProject1"
     x:Name="Window"
    Title="Window1"
    Width="640" Height="480">
       

    <Window.Resources>
                <local:MyValueClass x:Key="myvalue" Value="18.545"/>
            
       <DoubleAnimationUsingKeyFrames x:Key="thisOne"
                       BeginTime="00:00:00"
                       Storyboard.TargetName="rectangle"
                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
    <SplineDoubleKeyFrame KeyTime="00:00:0.5" Value="{Binding Source={StaticResouce myvalue}, Path=Value}"/>
    </DoubleAnimationUsingKeyFrames>

    </Window.Resources>

    ....
    </Window>

    code behind

      public class MyValueClass:INotifyPropertyChanged
        {
            private double _value;
            public double Value
            {
                get { return _value; }
                set {
                    _value = value;
                    OnPropertyChanged("Value");               
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            private void OnPropertyChanged(string propname)
            {
                if(PropertyChanged !=null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propname));
                }
            }
        }

    the code to change the property value:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
                (this.Resources["myvalue"] as MyValueClass).Value = 15;
    }

    Hope this helps.

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked As Answer byzaurska Wednesday, November 04, 2009 10:41 PM
    •  

All Replies

  • Friday, October 30, 2009 9:13 AMLinda LiuMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi Zaurska,

    Using DynamicResource markup extensions in XAML equals to setting resource reference in code. For example:
    XAML
    <TextBlock Name="txtbox" Background="{DynamicResource myBrush}"/>

    code behind
    this.txtbox.SetResourceReference(TextBlock.BackgroundProperty, "myBrush");

    Note that only FrameworkElement or FrameworkContentElement or FrameworkElementFactory class has the SetResourceReference method. That's to say, we can only associate property with a resource on FrameworkElement or FrameworkContentElement or FrameworkElementFactory. The SplineDoubleKeyFrame is not any of above types, so it couldn't be associated with a resource, i.e. using DynamicResource on the SplineDoubleKeyFrame has no effect.

    Changing the "DynamicResource" to "StaticResource" in the XAML can solve the problem. For example:

    <DoubleAnimationUsingKeyFrames x:Key="thisOne"
                       BeginTime="00:00:00"
                       Storyboard.TargetName="rectangle"
                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
    <SplineDoubleKeyFrame KeyTime="00:00:0.5" Value="{StaticResource sdKey}"/>
    </DoubleAnimationUsingKeyFrames>


    Hope this helps.
    If you have any question, please feel free to let me know.

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
  • Monday, November 02, 2009 9:37 AMzaurska Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    thank you,

     I need sdKey to increment at runtime, and the storyboard to respond to that change, if its a Static resource I cant change it, can I? 

    In code behind I have done this instead:

                        Double currentAngle =Convert.ToDouble(
                             ((TransformGroup)r.RenderTransform)
                             .Children[2].GetValue(RotateTransform.AngleProperty)
                             .ToString());
    
                        double d = currentAngle + 18;
    
                        ((SplineDoubleKeyFrame)daukf.KeyFrames[0]).Value = d;
    
    which does what I need.

    I'd still like to do it in Xaml though


  • Monday, November 02, 2009 10:42 AMLinda LiuMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    Hi Zaurska,

    You can bind the Value property of the SplineDoubleKeyFrame to a property of a business class. Change the value of the business class property at run time and the SplineDoubleKeyFrame.Value property will be changed. For example:

    <Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="UntitledProject1.Window1"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    xmlns:local="clr-namespace:UntitledProject1"
     x:Name="Window"
    Title="Window1"
    Width="640" Height="480">
       

    <Window.Resources>
                <local:MyValueClass x:Key="myvalue" Value="18.545"/>
            
       <DoubleAnimationUsingKeyFrames x:Key="thisOne"
                       BeginTime="00:00:00"
                       Storyboard.TargetName="rectangle"
                       Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
    <SplineDoubleKeyFrame KeyTime="00:00:0.5" Value="{Binding Source={StaticResouce myvalue}, Path=Value}"/>
    </DoubleAnimationUsingKeyFrames>

    </Window.Resources>

    ....
    </Window>

    code behind

      public class MyValueClass:INotifyPropertyChanged
        {
            private double _value;
            public double Value
            {
                get { return _value; }
                set {
                    _value = value;
                    OnPropertyChanged("Value");               
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            private void OnPropertyChanged(string propname)
            {
                if(PropertyChanged !=null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propname));
                }
            }
        }

    the code to change the property value:

    private void button1_Click(object sender, RoutedEventArgs e)
    {
                (this.Resources["myvalue"] as MyValueClass).Value = 15;
    }

    Hope this helps.

    Sincerely,
    Linda Liu


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked As Answer byzaurska Wednesday, November 04, 2009 10:41 PM
    •  
  • Wednesday, November 04, 2009 10:41 PMzaurska Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    even better,

    thanks so much!