c# wpf xaml resources dynamicresource

c# - resourcedictionary wpf



Coloque el guión gráfico en los recursos de la aplicación (3)

FINALMENTE ENCONTRÉ LA SOLUCIÓN !!!!!

Si recuerdas el error que tuve al colocar el guión gráfico en el archivo app.xaml fue:

No se puede establecer una propiedad en el objeto ''System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames'' porque está en estado de solo lectura.

en otras palabras, no pude modificar la propiedad del objetivo del guión gráfico, solo pude redirigirlo. entonces la solución fue cambiar Storyboard.TargetName="grid" para Storyboard.TargetName="{binding}"

Déjame juntar todo:

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

// reemplaza el Storyboard.TargetName = "grid" para Storyboard.TargetName = "{Binding}". // Su recurso de guion gráfico no debería verse así:

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

NOTA IMPORTANTE:

sabiendo que al crear su guión gráfico con mezcla de expresiones, a veces la mezcla de expresiones creará un grupo de transformación de renderizado al control que está animando. en este ejemplo, yo animé a un huésped. y para que esa interna sea animada, necesitaba tener

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

En otras palabras, si su animación trata con scaletransform skewtransform, etc., coloque ese grupo de transformación de representación en todos los objetos que planea animar.

Finalmente puedo animar:

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

Necesito usar el mismo guión gráfico en varios lugares, por lo tanto, coloqué el guión gráfico dentro de mi Application.Resources. Cuando intento ejecutar el guión gráfico, el único problema es que necesito hacer referencia al objetivo que quiero animar. Aquí está mi guión gráfico:

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

la forma en que animo la altura de un objeto diferente es cambiando el objetivo de recurso dinámico. Pude hacerlo cuando el guión gráfico estaba en la ventana actual. Pero ahora que quiero ubicarlo en los recursos de la aplicación, no sé cómo hacer referencia a la propiedad de destino.

EDITAR

La solución que publiqué anteriormente funciona bien, pero a veces es difícil crear animaciones complejas con código. entonces, otra solución alternativa que resolví fue crear el guión gráfico con expresión mezcla. así que arrastro un control aleatorio a la ventana principal en la mezcla de expresiones y creo una animación aleatoria. digamos que la animación sale como:

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

luego copio ese código y lo pego en mi ventana de trabajo NO EN LA APLICACIÓN.XAML.

y luego en mi código digamos que tengo un:

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

por alguna razón, el grupo de transformación debe estar allí para animar el objeto. de todos modos, digamos que tengo esa frontera en mi ventana de trabajo y quiero animarla con la misma animación que creé con la mezcla de expresiones. lo que haré en el código es:

Storyboard sb1 = FindResource("Storyboard1") as Storyboard; foreach (var child in sb1.Children) { Storyboard.SetTargetName(child, brdBorder.Name); } sb1.Begin(this);

y luego puedo animar ese borde en mi ventana de trabajo. Lo bueno de esto es que puedo aplicar la misma animación a varios objetos (creo que es el propósito de crear un recurso), el problema surge cuando trato de colocar el guión gráfico en un diccionario de recursos o en la aplicación.xaml archivo. Cuando hago eso, c # puede encontrar el guión gráfico, pero las propiedades del guión gráfico son de solo lectura, por lo tanto, aparece el siguiente error:

Cannot set a property on object ''System.Windows.Media.Animation.DoubleAnimationUsingKeyFrames'' because it is in a read-only state.

La razón por la que quería hacer esto es aplicar la misma animación a múltiples objetos. Una solución alternativa fue crear la animación básica con código y luego la animación más compleja, como la función de aceleración, etc., guardarla como recurso. Déjame mostrarte lo que quiero decir.

En mi archivo de recursos coloqué el siguiente recurso:

<EasingDoubleKeyFrame x:Key="pleaseWork"> <EasingDoubleKeyFrame.EasingFunction > <BackEase EasingMode="EaseOut" Amplitude="1"/> </EasingDoubleKeyFrame.EasingFunction> </EasingDoubleKeyFrame>

En expresion blend puedes construir una función de facilidad más compleja. Luego, con el código detrás, crearé un guión gráfico básico:

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

Esto me permitió usar el mismo guión gráfico en múltiples objetos.


No necesita hacer referencia al objetivo en ninguna parte, solo puede crear uno localmente, esta es una de las características más importantes de la búsqueda dinámica de recursos, por ej.

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


Para

Aplicación Windows Phone 8.1

Me enfrenté al mismo problema y agregué para mezclar muchas soluciones para lograr esto.

Este es mi archivo 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>

En mi página, tengo algo como esto ( page.xaml )

<Grid x:Name="ViewPanel" Canvas.Left="0" Canvas.ZIndex="1"> //Etc .... </Grid>

Ahora, vincula este método a un evento (toque el botón u otra cosa)

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

¡Espero que le ayudará!