11

複数の場所で同じストーリーボードを使用する必要があるため、ストーリーボードを Application.Resources 内に配置しました。ストーリーボードを実行しようとすると、アニメーション化するターゲットを参照する必要があるという唯一の問題があります。これが私のストーリーボードです:

    <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>

次に、そのコードをコピーして、APP.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();

これにより、複数のオブジェクトで同じストーリーボードを使用できるようになりました。

4

3 に答える 3

26

ターゲットをどこからでも参照する必要はありません。ローカルでターゲットを作成するだけで済みます。これは、動的リソース検索の優れた機能の 1 つです。

<!-- 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>
于 2011-08-11T15:02:03.833 に答える
7

最後に私は解決策を見つけました!!!!!

ストーリーボードを app.xaml ファイルに配置したときに発生したエラーを思い出してください。

読み取り専用状態であるため、オブジェクト 'System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames' にプロパティを設定できません。

つまり、ストーリーボードのターゲット プロパティを変更できませんでした。Storyboard.TargetName="grid"したがって、解決策はforを変更することでした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="{Binding}" の Storyboard.TargetName="grid" を置き換えます。// ストーリーボード リソースは次のようになってはいけません:

<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>

つまり、アニメーションで scaletransform、skewtransform などを扱う場合は、アニメーション化する予定のすべてのオブジェクトにそのレンダリング トランスフォーム グループを配置します。


最後に私はアニメーション化することができます:

<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);
于 2011-08-11T19:13:51.960 に答える