Разместите раскадровку в ресурсах приложений

Мне нужно использовать одну и ту же раскадровку в нескольких местах, поэтому я разместил раскадровку внутри своего приложения. Ресурсы. Когда я пытаюсь выполнить раскадровку, единственная проблема заключается в том, что мне нужно ссылаться на цель, которую я хочу оживить. Вот моя раскадровка:

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

способ анимации другой высоты объекта - это изменение цели динамического ресурса. Я смог сделать это, когда раскадровка находилась в текущем окне. Но теперь, когда я хочу разместить его в ресурсах приложения, я не знаю, как ссылаться на целевое свойство.


EDIT

Решение, которое я опубликовал ранее, работает хорошо, но иногда сложно создавать сложные анимации с кодом. поэтому другое альтернативное решение, которое я разработал, состояло в том, чтобы создать раскадровку с помощью выражения blend. поэтому я перетаскиваю случайный элемент управления в главное окно в виде blend и создаю случайную анимацию. скажем, анимация выдается как:

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

по какой-то причине группа преобразования должна быть там, чтобы анимировать объект. в любом случае позвольте сказать, что у меня есть этот пограничник в моем рабочем окне, и я хочу оживить его с той же анимацией, которую я создал с помощью выражения blend. что я буду делать в коде:

Storyboard sb1 = FindResource("Storyboard1") as Storyboard;

foreach (var child in sb1.Children)
{
    Storyboard.SetTargetName(child, brdBorder.Name);
}

sb1.Begin(this);

а затем я могу анимировать эту рамку в рабочем окне. Приятная часть этого заключается в том, что я могу применить одну и ту же анимацию к нескольким объектам (цель создания ресурса, я думаю), проблема возникает, когда я пытаюсь разместить раскадровку в словаре ресурсов или в app.xaml файл. когда я это делаю, С# может найти раскадровку, но свойства раскадровки читаются только поэтому я получаю ошибку:

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>

В expresion blend вы можете создать более сложную функцию облегчения. Затем с кодом позади я создам базовую раскадровку:

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();

Это позволило мне использовать одну и ту же раскадровку для нескольких объектов.

Ответ 1

НАКОНЕЦ Я НАШЕЛ РЕШЕНИЕ!!!!!

Если вы помните ошибку, которую я получил при размещении раскадровки в файле 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 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);

ПРИМЕЧАНИЕ ВАЖНО:

осознавая, что при создании раскадровки с использованием blend-выражения иногда выражение blend создает группу преобразования визуализации для элемента управления, который вы анималируете. в этом примере я, где анимация границы. и для того, чтобы анимировать этот пограничник, ему нужно было

           <Border.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Border.RenderTransform>

Другими словами, если ваша анимация имеет дело с skettransform scaletransform и т.д., тогда поместите эту группу преобразований для всех объектов, которые вы планируете анимации.


finaly Я могу анимировать:

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

Ответ 2

Вам не нужно ссылаться на цель в любом месте, вы можете просто создать ее локально, это одна из замечательных функций динамического поиска ресурсов, например.

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

Ответ 3

При a

Приложение 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();
        }

Я надеюсь, что это поможет!