将情节提要放在应用程序资源中
本文关键字:应用程序 资源 | 更新日期: 2023-09-27 18:00:26
我需要在多个地方使用相同的情节提要,因此我将情节提要放在我的应用程序资源中。当我尝试执行情节提要时,唯一的问题是我需要引用要进行动画处理的目标。这是我的故事板:
<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>
我为不同对象的高度设置动画的方式是通过更改动态资源目标。当故事板位于当前窗口中时,我能够这样做。但是现在我想把它放在应用程序资源中,我不知道如何引用目标属性。
编辑
我之前发布的解决方案效果很好,但有时很难用代码创建复杂的动画。 因此,我制定的另一个替代解决方案是使用表达式混合创建故事板。 所以我在表达式混合中将随机控件拖到主窗口并创建一个随机动画。 假设动画显示为:
<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>
然后我复制该代码并将其粘贴到我的工作窗口中,而不是在应用程序中。XAML。
然后在我的代码中,假设我有一个:
<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>
出于某种原因,转换组必须在那里才能对对象进行动画处理。 无论如何,假设我的工作窗口中有那个边界,我想使用我使用表达式混合创建的相同动画对其进行动画处理。 我将在代码中做的是:
Storyboard sb1 = FindResource("Storyboard1") as Storyboard;
foreach (var child in sb1.Children)
{
Storyboard.SetTargetName(child, brdBorder.Name);
}
sb1.Begin(this);
然后我能够在工作窗口上对该边框进行动画处理。这样做的好处是我能够将相同的动画应用于多个对象(我认为这是创建资源的目的(,当我尝试将情节提要放置在资源字典或 app.xaml 文件中时,问题就出现了。当我这样做时,C# 能够找到情节提要,但情节提要的属性是只读的,因此我收到错误:
Cannot set a property on object 'System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames' because it is in a read-only state.
我想这样做的原因是将相同的动画应用于多个对象。解决方法是使用代码构建基本动画,然后更复杂的动画(如缓动函数等(将其保存为资源。让我告诉你我的意思。
在我的资源文件中,我放置了以下资源:
<EasingDoubleKeyFrame x:Key="pleaseWork">
<EasingDoubleKeyFrame.EasingFunction >
<BackEase EasingMode="EaseOut" Amplitude="1"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
在表达式混合中,您可以构建更复杂的缓动函数。然后,使用隐藏的代码,我将创建一个基本的故事板:
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();
这使我能够在多个对象上使用相同的情节提要。
在任何地方引用目标,你可以在本地创建一个,这是动态资源查找的一大特点,例如
<!-- No more target here! -->
<Application.Resources>
<Storyboard x:Key="SB_Height" x:Shared="False">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)"
Storyboard.TargetName="{DynamicResource AnimationTarget}">
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="90">
<EasingDoubleKeyFrame.EasingFunction>
<CircleEase EasingMode="EaseOut" />
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Application.Resources>
<!-- Somewhere else... -->
<Button Name="mybutton" Content="Test" Height="20">
<Button.Resources>
<sys:String x:Key="AnimationTarget">mybutton</sys:String>
</Button.Resources>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard Storyboard="{StaticResource SB_Height}"/>
</EventTrigger>
</Button.Triggers>
</Button>
终于找到了解决方案
!!!!如果您还记得我在 app.xaml 文件中放置情节提要时遇到的错误是:
无法在对象"System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames"上设置属性,因为它处于只读状态。
换句话说,我无法修改故事板的目标属性,我只能将其红色。 所以解决方案是更改Storyboard.TargetName="grid"
Storyboard.TargetName="{binding}"
让我把所有东西放在一起:
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}"。 情节提要资源不应如下所示:
<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);
注意重要事项:
请注意,在使用表达式混合创建情节提要时,有时表达式混合会为正在设置动画的控件创建呈现转换组。 在这个例子中,我在哪里动画一个边界。 为了使该边界具有动画,它需要具有
<Border.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Border.RenderTransform>
换句话说,如果您的动画处理缩放变换倾斜变换等,则将该渲染变换组放置到您计划进行动画处理的所有对象。
最后,我能够制作动画:
<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);
对于
Windows Phone 8.1 应用程序
我遇到了同样的问题,我添加了许多解决方案来实现这一点。
这是我的 App.xaml 文件
<Application.Resources>
<ResourceDictionary>
<Storyboard x:Key="ShowMenuAnimationKey">
<DoubleAnimation
Storyboard.TargetName="{Binding}" //this is important
Storyboard.TargetProperty="(Canvas.Left)"
From="0" To="400" Duration="0:0:1">
</DoubleAnimation>
</Storyboard>
</ResourceDictionary>
</Application.Resources>
在我的页面中,我有这样的东西(page.xaml(
<Grid x:Name="ViewPanel"
Canvas.Left="0"
Canvas.ZIndex="1">
//Etc ....
</Grid>
现在,将此方法绑定到事件(按钮点击或其他内容(
Page.xaml.cs
private void MenuPanel_OnTap(object sender, GestureEventArgs e)
{
Storyboard sb = App.Current.Resources["ShowMenuAnimationKey"] as Storyboard;
sb.Stop();
Storyboard.SetTarget(sb, ViewPanel);
sb.Begin();
}
我希望这会有所帮助!