不使用Name的WPF Animate属性

时间:2013-07-29 19:44:02

标签: wpf xaml storyboard element children

我正在尝试在XAML中创建一个故事板,该故事板为一个元素的一个子元素的属性设置动画,该元素会引发一个事件。但是我似乎无法在不使用Names的情况下使用它,这是我在这种特定情况下无法真正做到的事情。

我基本上都在尝试这样的事情(当然要简化得多):

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

关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:5)

假设您在动画中编入索引的UIElement存在(即已存在于Canvas),那么您可以执行以下操作:

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

请注意我如何移动Trigger上方的按钮添加。如果按钮低于您问题中的Trigger,则尝试访问Children[0]会抛出ArgumentOutOfRangeException,因为此时没有儿童。

答案 1 :(得分:1)

要在动画中使用Storyboard.TargetProperty,它应该始终是依赖属性。 Children属性获取此UIElementCollectionPanel)的子元素Canvas。因此,以下构造Children [n]返回UIElement,它应该导致某种类型,以访问其依赖项属性。

这可以在代码中完成,如下所示:

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

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

默认情况下,动画中的所有这些操作都缺失,这是您的构造无法正常工作。

我建议在可能转换的代码中创建动画。

为了证明这一点,我在注册动画的Canvas事件中创建了一个Loaded。元素编号通过附加的依赖属性设置(当然,该示例可以以各种方式实现)。以下是我的例子:

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:访问Canvas中的项目只能在事件Loaded或结束时进行。否则,项目不可用,因为它们未加载。