将情节提要放置在应用程序资源中 [英] Place storyboard in application resources
问题描述
我需要在多个地方使用相同的故事板,因此将故事板放置在Application.Resources中。当我尝试执行情节提要时,唯一的问题是我需要引用要设置动画的目标。这是我的故事板:
I need to use the same storyboard in several places therefore I placed the storyboard inside my Application.Resources . When I try to execute the storyboard the only problem is that I need to reference the target that I want to animate. Here is my storyboard:
<System:String x:Key="target">border2</System:String>
<Storyboard x:Key="stHeight">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="(FrameworkElement.Height)"
Storyboard.TargetName="{DynamicResource target}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
我动画另一个对象的高度的方法是通过更改动态资源目标。当故事板在当前窗口中时,我能够执行此操作。但是现在我想将其放置在应用程序资源中,因此我不知道如何引用目标属性。
the way I animate a different object's height is by changing the dynamic resource target. I was able to do so when the storyboard was in the current window. But now that I want to place it in the application resources I don't know how to reference the target property.
我之前发布的解决方案效果很好但是有时候很难用代码创建复杂的动画。所以我想出的另一种替代解决方案是用表情混合创建故事板。所以我将一个随机控件拖到表达式混合的主窗口中并创建一个随机动画。假设动画显示为:
The solution that I posted earlier works nice but sometimes it is hard to create complex animations with code. so another alternate solution that I worked out was to create the storyboard with expression blend. so I drag a random control to the main window in expression blend and create a random animation. let's say the animation comes out as:
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="103"/>
</DoubleAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="grid">
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.75,0.5"/>
</PointAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
然后我复制该代码并将其粘贴到我的工作窗口中,而不是在APP.XAML中。
then I copy that code and paste it in on my working window NOT IN THE APP.XAML.
,然后在我的代码中假设我有一个:
and then in my code let's say I have a:
<Border Name="brdBorder" BorderBrush="Silver" BorderThickness="1" Margin="328,104,0,0" Background="#FFE52E2E" HorizontalAlignment="Left" Width="94" Height="100" VerticalAlignment="Top" >
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
出于某种原因,必须要有变换组才能为对象设置动画。无论如何,假设我的工作窗口中有该寄宿生,并且希望使用与表情融合创建的相同动画对其进行动画处理。我将在代码中执行的操作是:
for some reason the transform group has to be there in order to animate the object. anyways so let's say that I have that boarder in my working window and I want to animate it with the same animation that I created with expression blend. what I will do in code is:
Storyboard sb1 = FindResource("Storyboard1") as Storyboard;
foreach (var child in sb1.Children)
{
Storyboard.SetTargetName(child, brdBorder.Name);
}
sb1.Begin(this);
然后我可以在工作窗口上为该边框设置动画。这样做的好处是,我能够将相同的动画应用于多个对象(这是我认为创建资源的目的),当我尝试将情节提要放置在资源字典或app.xaml中时出现问题文件。当我这样做时,c#能够找到情节提要,但情节提要的属性是只读的,因此出现错误:
and then I am able to animate that border on my working window. The nice part of this is that I am able to apply the same animation to multiple objects (that is the purpose of creating a resource I think) the problem comes when I try to place the storyboard in a resource dictionary or in the app.xaml file. when I do that, c# is able to find the storyboard but the properties of the storyboard are read only therefore I get the error:
Cannot set a property on object 'System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames' because it is in a read-only state.
我想要这样做的原因是将相同的动画应用于多个对象。一种解决方法是使用代码构建基本动画,然后将诸如缓动功能等更复杂的动画另存为资源。让我告诉你我的意思。
The reason why I wanted to do this is to apply the same animation to multiple objects. A work around solution was to build the basic animation with code and then the more complex animation such as the easing function etc save it as a resource. Let me show you what I mean.
在我的资源文件中,放置了以下资源:
In my resources file I placed the following resource:
<EasingDoubleKeyFrame x:Key="pleaseWork">
<EasingDoubleKeyFrame.EasingFunction >
<BackEase EasingMode="EaseOut" Amplitude="1"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
在表达式混合中,您可以构建更复杂的缓动函数。然后,用后面的代码创建一个基本的故事板:
In expresion blend you can build a more complex ease function. Then with code behind I will create a basic storyboard:
DoubleAnimation animation = new DoubleAnimation();
animation.To = 336; // final value
//animation.From = 0;
//animation.BeginTime = TimeSpan.FromSeconds(0);
animation.Duration = new Duration(TimeSpan.FromSeconds(5)); // how much time should animation last
// here comes the magic:
// note that I can bind to EasingDoubleKeyFrame in my resource file in xaml
animation.EasingFunction = ((EasingDoubleKeyFrame)FindResource("pleaseWork")).EasingFunction; // apply the easing function
Storyboard.SetTarget(animation, groupBox1); // what object will be animated?
Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.HeightProperty)); // what property will be animated
Storyboard sb = new Storyboard();
sb.Children.Add(animation);
sb.Begin();
这使我可以在多个对象上使用相同的故事板。
This enabled me to use the same storyboard on multiple objects.
推荐答案
最后我找到了解决方案!!!!
FINALLY I FOUND THE SOLUTION!!!!!
如果您还记得将情节提要放在app.xaml文件中时遇到的错误是:
If you recall the error that I got when placing the storyboard in the app.xaml file was:
无法设置对象'System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames'的属性,因为它处于只读状态。
Cannot set a property on object 'System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames' because it is in a read-only state.
换句话说,我无法修改故事板的目标属性,我可以将其标记为红色。因此解决方案是将 Storyboard.TargetName = grid
更改为 Storyboard.TargetName = {binding}
in other words I could not modify the target property of the storyboard I could just red it. so the solution was to change the Storyboard.TargetName="grid"
for Storyboard.TargetName="{binding}"
让我将所有内容放在一起:
Let me put everything together:
step 1:
// create your custom storyboard with expression blend or xaml:
// let's say it comes out as:
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="103"/>
</DoubleAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="grid">
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.75,0.5"/>
</PointAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
-
step 2:
// copy and paste your storyboard to your app.xaml file or to a
// resource dictionary (if you paste it in a resource dictionary do not
// forget to merge the dictionaries so that your code is able to find the
// storyboard as a resource)
<Application x:Class="FilesPro2._1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="{Binding}">
<EasingDoubleK
....
.....
...
etc
-
step 3
//将Storyboard.TargetName = grid替换为Storyboard.TargetName = {Binding}。
//您的故事板资源应该看起来像这样:
// replace the Storyboard.TargetName="grid" for Storyboard.TargetName="{Binding}". // Your storyboard resource should no look like:
<Application.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="{Binding}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="{Binding}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="103"/>
</DoubleAnimationUsingKeyFrames>
<PointAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)" Storyboard.TargetName="{Binding}">
<EasingPointKeyFrame KeyTime="0:0:1" Value="0.75,0.5"/>
</PointAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="{Binding}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="75"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
-
step 4
//create a method to make it easy to run the same animation on multiple objects:
void runStoryboard(string storyboardName, string objectName)
{
Storyboard sb = FindResource(storyboardName) as Storyboard;
foreach (var child in sb.Children)
Storyboard.SetTargetName(child, objectName);
sb.Begin(this); // do not forget the this keyword
}
-
step 5
// start your animation with the object you wish to animate
runStoryboard("Storyboard1", brdBorder.Name);
要点:
注意使用表情混合创建故事板时,有时表情混合会为要设置动画的控件创建一个渲染变换组。在此示例中,我为寄宿生设置了动画。并且要使该寄宿生动起来,就需要
by aware that when creating your storyboard with expression blend, sometimes expression blend will create a render transform group to the control you are animating. in this example I where animating a boarder. and for that boarder to be animated it needed to have
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
换句话说,如果您的动画处理的是scaletransform,skewtransform等。您计划制作动画的所有对象。
In other words, if your animation deals with scaletransform skewtransform etc.. then place that render transform group to all the objects that you plan on animating.
最终我可以设置动画了:
finaly I am able to animate:
<Border Name="brdBorder" BorderBrush="Silver" BorderThickness="1" Margin="338,6,0,0" Background="#FFE52E2E" HorizontalAlignment="Left" Width="94" Height="38" VerticalAlignment="Top">
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
</Border>
// AND
<Button Name="mybutton" Content="Test" Height="20" Click="mybutton_Click">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
AS:
runStoryboard("Storyboard1", brdBorder.Name);
runStoryboard("Storyboard1", mybutton.Name);
这篇关于将情节提要放置在应用程序资源中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!