2013-07-29 11 views
5

Sto provando a creare uno storyboard in XAML che anima una proprietà di uno degli elementi figlio di un elemento che genera un evento. Ma non riesco a farlo funzionare senza usare Names, cosa che non posso davvero fare in questa situazione specifica.WPF Animate la proprietà del figlio senza utilizzare il nome

che sto fondamentalmente cercando qualcosa di simile (molto semplificata ovviamente):

<Canvas> 
     <Canvas.Triggers> 
     <EventTrigger RoutedEvent="FrameworkElement.Loaded"> 
      <EventTrigger.Actions> 
       <BeginStoryboard> 
        <Storyboard> 
        <DoubleAnimation Storyboard.TargetProperty="Children[0].(Canvas.Left)" From="0" To="400" /> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger.Actions> 
     </EventTrigger> 
     </Canvas.Triggers> 

     <Button Canvas.Left="20" Canvas.Top="20">A</Button> 
     <Button Canvas.Left="40" Canvas.Top="20">B</Button> 
    </Canvas> 

Delle idee su come questo potrebbe essere realizzato?

risposta

5

A condizione che il UIElement si sta Indicizzazione l'animazione esiste (cioè già presenti sul Canvas) allora si può fare quanto segue:

<Canvas x:Name="MyCanvas"> 
    <Button x:Name="btn" Canvas.Left="20" Canvas.Top="20">A</Button> 
    <Button Canvas.Left="40" Canvas.Top="20">B</Button> 
    <Canvas.Triggers> 
     <EventTrigger RoutedEvent="FrameworkElement.Loaded"> 
      <EventTrigger.Actions> 
       <BeginStoryboard> 
        <Storyboard> 
         <DoubleAnimation Storyboard.Target="{Binding ElementName=MyCanvas, Path=Children[0]}" 
             Storyboard.TargetProperty="(Canvas.Left)" From="0" To="400" /> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger.Actions> 
     </EventTrigger> 
    </Canvas.Triggers> 
</Canvas> 

Notate come ho spostato l'aggiunta dei pulsanti sopra il Trigger . Se i pulsanti sono sotto il Trigger come nella tua domanda, provare ad accedere a Children[0] genererà un ArgumentOutOfRangeException perché non ci sono bambini a questo punto.

+1

Sì! Hai vinto, +1 =). –

1

Per utilizzare Storyboard.TargetProperty nell'animazione, deve sempre essere una proprietà di dipendenza. La proprietà Children ottiene uno UIElementCollection di elementi figlio di questo Panel (Canvas). Pertanto, la seguente costruzione Children [n] restituisce UIElement, che dovrebbe portare a un determinato tipo, per accedere alla relativa proprietà di dipendenza.

questo può essere fatto nel codice come segue:

Button MyButton = (Button)MyCanvas.Children[0]; 

MessageBox.Show(MyButton.Width.ToString()); 

Tutte queste azioni mancanti nell'animazione per impostazione predefinita, questa è la vostra costruzione non funzionerà.

Propongo di creare animazioni nel codice in cui è possibile questa conversione.

Per dimostrarlo, ho creato un , nell'evento Loaded con animazione registrata. Il numero dell'elemento viene impostato tramite una proprietà di dipendenza allegata (ovviamente, l'esempio può essere implementato in vari modi). Qui di seguito è il mio esempio:

XAML

<Grid> 
    <local:MyCanvas x:Name="MyCanvas" local:ClassForAnimation.Children="1"> 
     <Button Canvas.Left="20" Canvas.Top="20">A</Button> 
     <Button Canvas.Left="40" Canvas.Top="20">B</Button> 
    </local:MyCanvas> 
</Grid> 

Code behind

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    }  
} 

public class MyCanvas : Canvas 
{ 
    public MyCanvas() 
    { 
     this.Loaded += new RoutedEventHandler(MyCanvas_Loaded); 
    } 

    private void MyCanvas_Loaded(object sender, RoutedEventArgs e) 
    { 
     MyCanvas myCanvas = sender as MyCanvas; 

     // Get No. of children 
     int children = ClassForAnimation.GetChildren(myCanvas); 

     // Get current Button for animation 
     Button MyButton = (Button)myCanvas.Children[children]; 

     if (myCanvas != null) 
     { 
      DoubleAnimation doubleAnimation = new DoubleAnimation(); 

      doubleAnimation.From = 0; 
      doubleAnimation.To = 400; 

      MyButton.BeginAnimation(Button.WidthProperty, doubleAnimation); 
     } 
    } 
} 

public class ClassForAnimation : DependencyObject 
{ 
    public static readonly DependencyProperty ChildrenProperty; 

    public static void SetChildren(DependencyObject DepObject, int value) 
    { 
     DepObject.SetValue(ChildrenProperty, value); 
    } 

    public static int GetChildren(DependencyObject DepObject) 
    { 
     return (int)DepObject.GetValue(ChildrenProperty); 
    } 

    static ClassForAnimation() 
    { 
     PropertyMetadata MyPropertyMetadata = new PropertyMetadata(0); 

     ChildrenProperty = DependencyProperty.RegisterAttached("Children", 
                  typeof(int), 
                  typeof(ClassForAnimation), 
                  MyPropertyMetadata); 
    }  
} 

Note: L'accesso alle voci del Canvas dovrebbe essere fatto solo in caso Loaded, o quando si è concluso. Altrimenti, gli articoli non sono disponibili perché non sono caricati.

Problemi correlati